diff options
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 99 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mr.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/port.c | 87 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 510 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 20 |
11 files changed, 675 insertions, 120 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index f0612645de99..7567437dbd34 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -177,18 +177,18 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, | |||
177 | 177 | ||
178 | props->max_mr_size = ~0ull; | 178 | props->max_mr_size = ~0ull; |
179 | props->page_size_cap = dev->dev->caps.page_size_cap; | 179 | props->page_size_cap = dev->dev->caps.page_size_cap; |
180 | props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; | 180 | props->max_qp = dev->dev->quotas.qp; |
181 | props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; | 181 | props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; |
182 | props->max_sge = min(dev->dev->caps.max_sq_sg, | 182 | props->max_sge = min(dev->dev->caps.max_sq_sg, |
183 | dev->dev->caps.max_rq_sg); | 183 | dev->dev->caps.max_rq_sg); |
184 | props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; | 184 | props->max_cq = dev->dev->quotas.cq; |
185 | props->max_cqe = dev->dev->caps.max_cqes; | 185 | props->max_cqe = dev->dev->caps.max_cqes; |
186 | props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; | 186 | props->max_mr = dev->dev->quotas.mpt; |
187 | props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; | 187 | props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; |
188 | props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; | 188 | props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; |
189 | props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; | 189 | props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; |
190 | props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; | 190 | props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; |
191 | props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; | 191 | props->max_srq = dev->dev->quotas.srq; |
192 | props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1; | 192 | props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1; |
193 | props->max_srq_sge = dev->dev->caps.max_srq_sge; | 193 | props->max_srq_sge = dev->dev->caps.max_srq_sge; |
194 | props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES; | 194 | props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index ae8eb4c4fb6c..65d41b76fa2c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -1687,7 +1687,7 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave | |||
1687 | vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; | 1687 | vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; |
1688 | if (NO_INDX != vp_oper->vlan_idx) { | 1688 | if (NO_INDX != vp_oper->vlan_idx) { |
1689 | __mlx4_unregister_vlan(&priv->dev, | 1689 | __mlx4_unregister_vlan(&priv->dev, |
1690 | port, vp_oper->vlan_idx); | 1690 | port, vp_oper->state.default_vlan); |
1691 | vp_oper->vlan_idx = NO_INDX; | 1691 | vp_oper->vlan_idx = NO_INDX; |
1692 | } | 1692 | } |
1693 | if (NO_INDX != vp_oper->mac_idx) { | 1693 | if (NO_INDX != vp_oper->mac_idx) { |
@@ -1718,6 +1718,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, | |||
1718 | if (cmd == MLX4_COMM_CMD_RESET) { | 1718 | if (cmd == MLX4_COMM_CMD_RESET) { |
1719 | mlx4_warn(dev, "Received reset from slave:%d\n", slave); | 1719 | mlx4_warn(dev, "Received reset from slave:%d\n", slave); |
1720 | slave_state[slave].active = false; | 1720 | slave_state[slave].active = false; |
1721 | slave_state[slave].old_vlan_api = false; | ||
1721 | mlx4_master_deactivate_admin_state(priv, slave); | 1722 | mlx4_master_deactivate_admin_state(priv, slave); |
1722 | for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { | 1723 | for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { |
1723 | slave_state[slave].event_eq[i].eqn = -1; | 1724 | slave_state[slave].event_eq[i].eqn = -1; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 85d91665d400..b5554121aca4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -417,7 +417,6 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, | |||
417 | struct mlx4_en_priv *priv = netdev_priv(dev); | 417 | struct mlx4_en_priv *priv = netdev_priv(dev); |
418 | struct mlx4_en_dev *mdev = priv->mdev; | 418 | struct mlx4_en_dev *mdev = priv->mdev; |
419 | int err; | 419 | int err; |
420 | int idx; | ||
421 | 420 | ||
422 | en_dbg(HW, priv, "Killing VID:%d\n", vid); | 421 | en_dbg(HW, priv, "Killing VID:%d\n", vid); |
423 | 422 | ||
@@ -425,10 +424,7 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, | |||
425 | 424 | ||
426 | /* Remove VID from port VLAN filter */ | 425 | /* Remove VID from port VLAN filter */ |
427 | mutex_lock(&mdev->state_lock); | 426 | mutex_lock(&mdev->state_lock); |
428 | if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx)) | 427 | mlx4_unregister_vlan(mdev->dev, priv->port, vid); |
429 | mlx4_unregister_vlan(mdev->dev, priv->port, idx); | ||
430 | else | ||
431 | en_dbg(HW, priv, "could not find vid %d in cache\n", vid); | ||
432 | 428 | ||
433 | if (mdev->device_up && priv->port_up) { | 429 | if (mdev->device_up && priv->port_up) { |
434 | err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); | 430 | err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index c151e7a6710a..c3e70bc2d875 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -177,6 +177,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
177 | struct mlx4_cmd_mailbox *outbox, | 177 | struct mlx4_cmd_mailbox *outbox, |
178 | struct mlx4_cmd_info *cmd) | 178 | struct mlx4_cmd_info *cmd) |
179 | { | 179 | { |
180 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
180 | u8 field; | 181 | u8 field; |
181 | u32 size; | 182 | u32 size; |
182 | int err = 0; | 183 | int err = 0; |
@@ -185,18 +186,26 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
185 | #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 | 186 | #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 |
186 | #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 | 187 | #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 |
187 | #define QUERY_FUNC_CAP_FMR_OFFSET 0x8 | 188 | #define QUERY_FUNC_CAP_FMR_OFFSET 0x8 |
188 | #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10 | 189 | #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP 0x10 |
189 | #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14 | 190 | #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP 0x14 |
190 | #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x18 | 191 | #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP 0x18 |
191 | #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x20 | 192 | #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP 0x20 |
192 | #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x24 | 193 | #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP 0x24 |
193 | #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x28 | 194 | #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP 0x28 |
194 | #define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c | 195 | #define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c |
195 | #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30 | 196 | #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30 |
196 | 197 | ||
198 | #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50 | ||
199 | #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54 | ||
200 | #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58 | ||
201 | #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60 | ||
202 | #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64 | ||
203 | #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68 | ||
204 | |||
197 | #define QUERY_FUNC_CAP_FMR_FLAG 0x80 | 205 | #define QUERY_FUNC_CAP_FMR_FLAG 0x80 |
198 | #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 | 206 | #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 |
199 | #define QUERY_FUNC_CAP_FLAG_ETH 0x80 | 207 | #define QUERY_FUNC_CAP_FLAG_ETH 0x80 |
208 | #define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10 | ||
200 | 209 | ||
201 | /* when opcode modifier = 1 */ | 210 | /* when opcode modifier = 1 */ |
202 | #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 | 211 | #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 |
@@ -237,8 +246,9 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
237 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY); | 246 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY); |
238 | 247 | ||
239 | } else if (vhcr->op_modifier == 0) { | 248 | } else if (vhcr->op_modifier == 0) { |
240 | /* enable rdma and ethernet interfaces */ | 249 | /* enable rdma and ethernet interfaces, and new quota locations */ |
241 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA); | 250 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | |
251 | QUERY_FUNC_CAP_FLAG_QUOTAS); | ||
242 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); | 252 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); |
243 | 253 | ||
244 | field = dev->caps.num_ports; | 254 | field = dev->caps.num_ports; |
@@ -250,14 +260,20 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
250 | field = 0; /* protected FMR support not available as yet */ | 260 | field = 0; /* protected FMR support not available as yet */ |
251 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); | 261 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); |
252 | 262 | ||
253 | size = dev->caps.num_qps; | 263 | size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave]; |
254 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); | 264 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); |
265 | size = dev->caps.num_qps; | ||
266 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); | ||
255 | 267 | ||
256 | size = dev->caps.num_srqs; | 268 | size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave]; |
257 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); | 269 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); |
270 | size = dev->caps.num_srqs; | ||
271 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); | ||
258 | 272 | ||
259 | size = dev->caps.num_cqs; | 273 | size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave]; |
260 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); | 274 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); |
275 | size = dev->caps.num_cqs; | ||
276 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); | ||
261 | 277 | ||
262 | size = dev->caps.num_eqs; | 278 | size = dev->caps.num_eqs; |
263 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); | 279 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); |
@@ -265,14 +281,19 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
265 | size = dev->caps.reserved_eqs; | 281 | size = dev->caps.reserved_eqs; |
266 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); | 282 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); |
267 | 283 | ||
268 | size = dev->caps.num_mpts; | 284 | size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave]; |
269 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); | 285 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); |
286 | size = dev->caps.num_mpts; | ||
287 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); | ||
270 | 288 | ||
271 | size = dev->caps.num_mtts; | 289 | size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave]; |
272 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); | 290 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); |
291 | size = dev->caps.num_mtts; | ||
292 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); | ||
273 | 293 | ||
274 | size = dev->caps.num_mgms + dev->caps.num_amgms; | 294 | size = dev->caps.num_mgms + dev->caps.num_amgms; |
275 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); | 295 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); |
296 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); | ||
276 | 297 | ||
277 | } else | 298 | } else |
278 | err = -EINVAL; | 299 | err = -EINVAL; |
@@ -287,7 +308,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, | |||
287 | u32 *outbox; | 308 | u32 *outbox; |
288 | u8 field, op_modifier; | 309 | u8 field, op_modifier; |
289 | u32 size; | 310 | u32 size; |
290 | int err = 0; | 311 | int err = 0, quotas = 0; |
291 | 312 | ||
292 | op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ | 313 | op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ |
293 | 314 | ||
@@ -311,6 +332,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, | |||
311 | goto out; | 332 | goto out; |
312 | } | 333 | } |
313 | func_cap->flags = field; | 334 | func_cap->flags = field; |
335 | quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS); | ||
314 | 336 | ||
315 | MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); | 337 | MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); |
316 | func_cap->num_ports = field; | 338 | func_cap->num_ports = field; |
@@ -318,29 +340,50 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, | |||
318 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); | 340 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); |
319 | func_cap->pf_context_behaviour = size; | 341 | func_cap->pf_context_behaviour = size; |
320 | 342 | ||
321 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); | 343 | if (quotas) { |
322 | func_cap->qp_quota = size & 0xFFFFFF; | 344 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); |
345 | func_cap->qp_quota = size & 0xFFFFFF; | ||
323 | 346 | ||
324 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); | 347 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); |
325 | func_cap->srq_quota = size & 0xFFFFFF; | 348 | func_cap->srq_quota = size & 0xFFFFFF; |
326 | 349 | ||
327 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); | 350 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); |
328 | func_cap->cq_quota = size & 0xFFFFFF; | 351 | func_cap->cq_quota = size & 0xFFFFFF; |
329 | 352 | ||
353 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); | ||
354 | func_cap->mpt_quota = size & 0xFFFFFF; | ||
355 | |||
356 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); | ||
357 | func_cap->mtt_quota = size & 0xFFFFFF; | ||
358 | |||
359 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); | ||
360 | func_cap->mcg_quota = size & 0xFFFFFF; | ||
361 | |||
362 | } else { | ||
363 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP); | ||
364 | func_cap->qp_quota = size & 0xFFFFFF; | ||
365 | |||
366 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP); | ||
367 | func_cap->srq_quota = size & 0xFFFFFF; | ||
368 | |||
369 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); | ||
370 | func_cap->cq_quota = size & 0xFFFFFF; | ||
371 | |||
372 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP); | ||
373 | func_cap->mpt_quota = size & 0xFFFFFF; | ||
374 | |||
375 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP); | ||
376 | func_cap->mtt_quota = size & 0xFFFFFF; | ||
377 | |||
378 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); | ||
379 | func_cap->mcg_quota = size & 0xFFFFFF; | ||
380 | } | ||
330 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); | 381 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); |
331 | func_cap->max_eq = size & 0xFFFFFF; | 382 | func_cap->max_eq = size & 0xFFFFFF; |
332 | 383 | ||
333 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); | 384 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); |
334 | func_cap->reserved_eq = size & 0xFFFFFF; | 385 | func_cap->reserved_eq = size & 0xFFFFFF; |
335 | 386 | ||
336 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); | ||
337 | func_cap->mpt_quota = size & 0xFFFFFF; | ||
338 | |||
339 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); | ||
340 | func_cap->mtt_quota = size & 0xFFFFFF; | ||
341 | |||
342 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); | ||
343 | func_cap->mcg_quota = size & 0xFFFFFF; | ||
344 | goto out; | 387 | goto out; |
345 | } | 388 | } |
346 | 389 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 179d26709c94..7d2628dfdc29 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -562,13 +562,17 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
562 | } | 562 | } |
563 | 563 | ||
564 | dev->caps.num_ports = func_cap.num_ports; | 564 | dev->caps.num_ports = func_cap.num_ports; |
565 | dev->caps.num_qps = func_cap.qp_quota; | 565 | dev->quotas.qp = func_cap.qp_quota; |
566 | dev->caps.num_srqs = func_cap.srq_quota; | 566 | dev->quotas.srq = func_cap.srq_quota; |
567 | dev->caps.num_cqs = func_cap.cq_quota; | 567 | dev->quotas.cq = func_cap.cq_quota; |
568 | dev->caps.num_eqs = func_cap.max_eq; | 568 | dev->quotas.mpt = func_cap.mpt_quota; |
569 | dev->caps.reserved_eqs = func_cap.reserved_eq; | 569 | dev->quotas.mtt = func_cap.mtt_quota; |
570 | dev->caps.num_mpts = func_cap.mpt_quota; | 570 | dev->caps.num_qps = 1 << hca_param.log_num_qps; |
571 | dev->caps.num_mtts = func_cap.mtt_quota; | 571 | dev->caps.num_srqs = 1 << hca_param.log_num_srqs; |
572 | dev->caps.num_cqs = 1 << hca_param.log_num_cqs; | ||
573 | dev->caps.num_mpts = 1 << hca_param.log_mpt_sz; | ||
574 | dev->caps.num_eqs = func_cap.max_eq; | ||
575 | dev->caps.reserved_eqs = func_cap.reserved_eq; | ||
572 | dev->caps.num_pds = MLX4_NUM_PDS; | 576 | dev->caps.num_pds = MLX4_NUM_PDS; |
573 | dev->caps.num_mgms = 0; | 577 | dev->caps.num_mgms = 0; |
574 | dev->caps.num_amgms = 0; | 578 | dev->caps.num_amgms = 0; |
@@ -2102,9 +2106,15 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
2102 | "aborting.\n"); | 2106 | "aborting.\n"); |
2103 | return err; | 2107 | return err; |
2104 | } | 2108 | } |
2105 | if (num_vfs > MLX4_MAX_NUM_VF) { | 2109 | |
2106 | printk(KERN_ERR "There are more VF's (%d) than allowed(%d)\n", | 2110 | /* Due to requirement that all VFs and the PF are *guaranteed* 2 MACS |
2107 | num_vfs, MLX4_MAX_NUM_VF); | 2111 | * per port, we must limit the number of VFs to 63 (since their are |
2112 | * 128 MACs) | ||
2113 | */ | ||
2114 | if (num_vfs >= MLX4_MAX_NUM_VF) { | ||
2115 | dev_err(&pdev->dev, | ||
2116 | "Requested more VF's (%d) than allowed (%d)\n", | ||
2117 | num_vfs, MLX4_MAX_NUM_VF - 1); | ||
2108 | return -EINVAL; | 2118 | return -EINVAL; |
2109 | } | 2119 | } |
2110 | 2120 | ||
@@ -2322,6 +2332,8 @@ slave_start: | |||
2322 | if (err) | 2332 | if (err) |
2323 | goto err_steer; | 2333 | goto err_steer; |
2324 | 2334 | ||
2335 | mlx4_init_quotas(dev); | ||
2336 | |||
2325 | for (port = 1; port <= dev->caps.num_ports; port++) { | 2337 | for (port = 1; port <= dev->caps.num_ports; port++) { |
2326 | err = mlx4_init_port_info(dev, port); | 2338 | err = mlx4_init_port_info(dev, port); |
2327 | if (err) | 2339 | if (err) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 348bb8c7d9a7..e582a41a802b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -455,6 +455,7 @@ struct mlx4_slave_state { | |||
455 | u8 last_cmd; | 455 | u8 last_cmd; |
456 | u8 init_port_mask; | 456 | u8 init_port_mask; |
457 | bool active; | 457 | bool active; |
458 | bool old_vlan_api; | ||
458 | u8 function; | 459 | u8 function; |
459 | dma_addr_t vhcr_dma; | 460 | dma_addr_t vhcr_dma; |
460 | u16 mtu[MLX4_MAX_PORTS + 1]; | 461 | u16 mtu[MLX4_MAX_PORTS + 1]; |
@@ -503,12 +504,28 @@ struct slave_list { | |||
503 | struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE]; | 504 | struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE]; |
504 | }; | 505 | }; |
505 | 506 | ||
507 | struct resource_allocator { | ||
508 | spinlock_t alloc_lock; /* protect quotas */ | ||
509 | union { | ||
510 | int res_reserved; | ||
511 | int res_port_rsvd[MLX4_MAX_PORTS]; | ||
512 | }; | ||
513 | union { | ||
514 | int res_free; | ||
515 | int res_port_free[MLX4_MAX_PORTS]; | ||
516 | }; | ||
517 | int *quota; | ||
518 | int *allocated; | ||
519 | int *guaranteed; | ||
520 | }; | ||
521 | |||
506 | struct mlx4_resource_tracker { | 522 | struct mlx4_resource_tracker { |
507 | spinlock_t lock; | 523 | spinlock_t lock; |
508 | /* tree for each resources */ | 524 | /* tree for each resources */ |
509 | struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; | 525 | struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; |
510 | /* num_of_slave's lists, one per slave */ | 526 | /* num_of_slave's lists, one per slave */ |
511 | struct slave_list *slave_list; | 527 | struct slave_list *slave_list; |
528 | struct resource_allocator res_alloc[MLX4_NUM_OF_RESOURCE_TYPE]; | ||
512 | }; | 529 | }; |
513 | 530 | ||
514 | #define SLAVE_EVENT_EQ_SIZE 128 | 531 | #define SLAVE_EVENT_EQ_SIZE 128 |
@@ -1111,7 +1128,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev, | |||
1111 | 1128 | ||
1112 | void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); | 1129 | void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); |
1113 | void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); | 1130 | void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); |
1114 | void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); | 1131 | void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); |
1115 | int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); | 1132 | int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); |
1116 | 1133 | ||
1117 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz); | 1134 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz); |
@@ -1252,4 +1269,6 @@ static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev) | |||
1252 | 1269 | ||
1253 | void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work); | 1270 | void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work); |
1254 | 1271 | ||
1272 | void mlx4_init_quotas(struct mlx4_dev *dev); | ||
1273 | |||
1255 | #endif /* MLX4_H */ | 1274 | #endif /* MLX4_H */ |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index f91719a08cba..63391a1a7f8c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c | |||
@@ -755,14 +755,14 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) | |||
755 | struct mlx4_mr_table *mr_table = &priv->mr_table; | 755 | struct mlx4_mr_table *mr_table = &priv->mr_table; |
756 | int err; | 756 | int err; |
757 | 757 | ||
758 | if (!is_power_of_2(dev->caps.num_mpts)) | ||
759 | return -EINVAL; | ||
760 | |||
761 | /* Nothing to do for slaves - all MR handling is forwarded | 758 | /* Nothing to do for slaves - all MR handling is forwarded |
762 | * to the master */ | 759 | * to the master */ |
763 | if (mlx4_is_slave(dev)) | 760 | if (mlx4_is_slave(dev)) |
764 | return 0; | 761 | return 0; |
765 | 762 | ||
763 | if (!is_power_of_2(dev->caps.num_mpts)) | ||
764 | return -EINVAL; | ||
765 | |||
766 | err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, | 766 | err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, |
767 | ~0, dev->caps.reserved_mrws, 0); | 767 | ~0, dev->caps.reserved_mrws, 0); |
768 | if (err) | 768 | if (err) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 946e0af5faef..caaa15470395 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c | |||
@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac); | |||
178 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) | 178 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) |
179 | { | 179 | { |
180 | u64 out_param = 0; | 180 | u64 out_param = 0; |
181 | int err; | 181 | int err = -EINVAL; |
182 | 182 | ||
183 | if (mlx4_is_mfunc(dev)) { | 183 | if (mlx4_is_mfunc(dev)) { |
184 | set_param_l(&out_param, port); | 184 | if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) { |
185 | err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, | 185 | err = mlx4_cmd_imm(dev, mac, &out_param, |
186 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, | 186 | ((u32) port) << 8 | (u32) RES_MAC, |
187 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | 187 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, |
188 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
189 | } | ||
190 | if (err && err == -EINVAL && mlx4_is_slave(dev)) { | ||
191 | /* retry using old REG_MAC format */ | ||
192 | set_param_l(&out_param, port); | ||
193 | err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, | ||
194 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, | ||
195 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
196 | if (!err) | ||
197 | dev->flags |= MLX4_FLAG_OLD_REG_MAC; | ||
198 | } | ||
188 | if (err) | 199 | if (err) |
189 | return err; | 200 | return err; |
190 | 201 | ||
@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) | |||
231 | u64 out_param = 0; | 242 | u64 out_param = 0; |
232 | 243 | ||
233 | if (mlx4_is_mfunc(dev)) { | 244 | if (mlx4_is_mfunc(dev)) { |
234 | set_param_l(&out_param, port); | 245 | if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) { |
235 | (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, | 246 | (void) mlx4_cmd_imm(dev, mac, &out_param, |
236 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, | 247 | ((u32) port) << 8 | (u32) RES_MAC, |
237 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | 248 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, |
249 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
250 | } else { | ||
251 | /* use old unregister mac format */ | ||
252 | set_param_l(&out_param, port); | ||
253 | (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, | ||
254 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, | ||
255 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
256 | } | ||
238 | return; | 257 | return; |
239 | } | 258 | } |
240 | __mlx4_unregister_mac(dev, port, mac); | 259 | __mlx4_unregister_mac(dev, port, mac); |
@@ -284,7 +303,7 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, | |||
284 | memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); | 303 | memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); |
285 | in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; | 304 | in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; |
286 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | 305 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, |
287 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); | 306 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); |
288 | 307 | ||
289 | mlx4_free_cmd_mailbox(dev, mailbox); | 308 | mlx4_free_cmd_mailbox(dev, mailbox); |
290 | 309 | ||
@@ -370,9 +389,12 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | |||
370 | u64 out_param = 0; | 389 | u64 out_param = 0; |
371 | int err; | 390 | int err; |
372 | 391 | ||
392 | if (vlan > 4095) | ||
393 | return -EINVAL; | ||
394 | |||
373 | if (mlx4_is_mfunc(dev)) { | 395 | if (mlx4_is_mfunc(dev)) { |
374 | set_param_l(&out_param, port); | 396 | err = mlx4_cmd_imm(dev, vlan, &out_param, |
375 | err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, | 397 | ((u32) port) << 8 | (u32) RES_VLAN, |
376 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, | 398 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, |
377 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | 399 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); |
378 | if (!err) | 400 | if (!err) |
@@ -384,23 +406,26 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | |||
384 | } | 406 | } |
385 | EXPORT_SYMBOL_GPL(mlx4_register_vlan); | 407 | EXPORT_SYMBOL_GPL(mlx4_register_vlan); |
386 | 408 | ||
387 | void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | 409 | void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) |
388 | { | 410 | { |
389 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; | 411 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; |
412 | int index; | ||
390 | 413 | ||
391 | if (index < MLX4_VLAN_REGULAR) { | 414 | mutex_lock(&table->mutex); |
392 | mlx4_warn(dev, "Trying to free special vlan index %d\n", index); | 415 | if (mlx4_find_cached_vlan(dev, port, vlan, &index)) { |
393 | return; | 416 | mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan); |
417 | goto out; | ||
394 | } | 418 | } |
395 | 419 | ||
396 | mutex_lock(&table->mutex); | 420 | if (index < MLX4_VLAN_REGULAR) { |
397 | if (!table->refs[index]) { | 421 | mlx4_warn(dev, "Trying to free special vlan index %d\n", index); |
398 | mlx4_warn(dev, "No vlan entry for index %d\n", index); | ||
399 | goto out; | 422 | goto out; |
400 | } | 423 | } |
424 | |||
401 | if (--table->refs[index]) { | 425 | if (--table->refs[index]) { |
402 | mlx4_dbg(dev, "Have more references for index %d," | 426 | mlx4_dbg(dev, "Have %d more references for index %d," |
403 | "no need to modify vlan table\n", index); | 427 | "no need to modify vlan table\n", table->refs[index], |
428 | index); | ||
404 | goto out; | 429 | goto out; |
405 | } | 430 | } |
406 | table->entries[index] = 0; | 431 | table->entries[index] = 0; |
@@ -410,23 +435,19 @@ out: | |||
410 | mutex_unlock(&table->mutex); | 435 | mutex_unlock(&table->mutex); |
411 | } | 436 | } |
412 | 437 | ||
413 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | 438 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) |
414 | { | 439 | { |
415 | u64 in_param = 0; | 440 | u64 out_param = 0; |
416 | int err; | ||
417 | 441 | ||
418 | if (mlx4_is_mfunc(dev)) { | 442 | if (mlx4_is_mfunc(dev)) { |
419 | set_param_l(&in_param, port); | 443 | (void) mlx4_cmd_imm(dev, vlan, &out_param, |
420 | err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, | 444 | ((u32) port) << 8 | (u32) RES_VLAN, |
421 | MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, | 445 | RES_OP_RESERVE_AND_MAP, |
422 | MLX4_CMD_WRAPPED); | 446 | MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, |
423 | if (!err) | 447 | MLX4_CMD_WRAPPED); |
424 | mlx4_warn(dev, "Failed freeing vlan at index:%d\n", | ||
425 | index); | ||
426 | |||
427 | return; | 448 | return; |
428 | } | 449 | } |
429 | __mlx4_unregister_vlan(dev, port, index); | 450 | __mlx4_unregister_vlan(dev, port, vlan); |
430 | } | 451 | } |
431 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); | 452 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); |
432 | 453 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index e891b058c1be..2715e61dbb74 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c | |||
@@ -480,8 +480,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) | |||
480 | */ | 480 | */ |
481 | 481 | ||
482 | err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, | 482 | err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, |
483 | (1 << 23) - 1, dev->phys_caps.base_sqpn + 8 + | 483 | (1 << 23) - 1, mlx4_num_reserved_sqps(dev), |
484 | 16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev), | ||
485 | reserved_from_top); | 484 | reserved_from_top); |
486 | if (err) | 485 | if (err) |
487 | return err; | 486 | return err; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index dd6876321116..b1603e2287a7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -55,6 +55,14 @@ struct mac_res { | |||
55 | u8 port; | 55 | u8 port; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct vlan_res { | ||
59 | struct list_head list; | ||
60 | u16 vlan; | ||
61 | int ref_count; | ||
62 | int vlan_index; | ||
63 | u8 port; | ||
64 | }; | ||
65 | |||
58 | struct res_common { | 66 | struct res_common { |
59 | struct list_head list; | 67 | struct list_head list; |
60 | struct rb_node node; | 68 | struct rb_node node; |
@@ -266,6 +274,7 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
266 | case RES_MPT: return "RES_MPT"; | 274 | case RES_MPT: return "RES_MPT"; |
267 | case RES_MTT: return "RES_MTT"; | 275 | case RES_MTT: return "RES_MTT"; |
268 | case RES_MAC: return "RES_MAC"; | 276 | case RES_MAC: return "RES_MAC"; |
277 | case RES_VLAN: return "RES_VLAN"; | ||
269 | case RES_EQ: return "RES_EQ"; | 278 | case RES_EQ: return "RES_EQ"; |
270 | case RES_COUNTER: return "RES_COUNTER"; | 279 | case RES_COUNTER: return "RES_COUNTER"; |
271 | case RES_FS_RULE: return "RES_FS_RULE"; | 280 | case RES_FS_RULE: return "RES_FS_RULE"; |
@@ -274,10 +283,139 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
274 | }; | 283 | }; |
275 | } | 284 | } |
276 | 285 | ||
286 | static void rem_slave_vlans(struct mlx4_dev *dev, int slave); | ||
287 | static inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave, | ||
288 | enum mlx4_resource res_type, int count, | ||
289 | int port) | ||
290 | { | ||
291 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
292 | struct resource_allocator *res_alloc = | ||
293 | &priv->mfunc.master.res_tracker.res_alloc[res_type]; | ||
294 | int err = -EINVAL; | ||
295 | int allocated, free, reserved, guaranteed, from_free; | ||
296 | |||
297 | if (slave > dev->num_vfs) | ||
298 | return -EINVAL; | ||
299 | |||
300 | spin_lock(&res_alloc->alloc_lock); | ||
301 | allocated = (port > 0) ? | ||
302 | res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] : | ||
303 | res_alloc->allocated[slave]; | ||
304 | free = (port > 0) ? res_alloc->res_port_free[port - 1] : | ||
305 | res_alloc->res_free; | ||
306 | reserved = (port > 0) ? res_alloc->res_port_rsvd[port - 1] : | ||
307 | res_alloc->res_reserved; | ||
308 | guaranteed = res_alloc->guaranteed[slave]; | ||
309 | |||
310 | if (allocated + count > res_alloc->quota[slave]) | ||
311 | goto out; | ||
312 | |||
313 | if (allocated + count <= guaranteed) { | ||
314 | err = 0; | ||
315 | } else { | ||
316 | /* portion may need to be obtained from free area */ | ||
317 | if (guaranteed - allocated > 0) | ||
318 | from_free = count - (guaranteed - allocated); | ||
319 | else | ||
320 | from_free = count; | ||
321 | |||
322 | if (free - from_free > reserved) | ||
323 | err = 0; | ||
324 | } | ||
325 | |||
326 | if (!err) { | ||
327 | /* grant the request */ | ||
328 | if (port > 0) { | ||
329 | res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] += count; | ||
330 | res_alloc->res_port_free[port - 1] -= count; | ||
331 | } else { | ||
332 | res_alloc->allocated[slave] += count; | ||
333 | res_alloc->res_free -= count; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | out: | ||
338 | spin_unlock(&res_alloc->alloc_lock); | ||
339 | return err; | ||
340 | } | ||
341 | |||
342 | static inline void mlx4_release_resource(struct mlx4_dev *dev, int slave, | ||
343 | enum mlx4_resource res_type, int count, | ||
344 | int port) | ||
345 | { | ||
346 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
347 | struct resource_allocator *res_alloc = | ||
348 | &priv->mfunc.master.res_tracker.res_alloc[res_type]; | ||
349 | |||
350 | if (slave > dev->num_vfs) | ||
351 | return; | ||
352 | |||
353 | spin_lock(&res_alloc->alloc_lock); | ||
354 | if (port > 0) { | ||
355 | res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] -= count; | ||
356 | res_alloc->res_port_free[port - 1] += count; | ||
357 | } else { | ||
358 | res_alloc->allocated[slave] -= count; | ||
359 | res_alloc->res_free += count; | ||
360 | } | ||
361 | |||
362 | spin_unlock(&res_alloc->alloc_lock); | ||
363 | return; | ||
364 | } | ||
365 | |||
366 | static inline void initialize_res_quotas(struct mlx4_dev *dev, | ||
367 | struct resource_allocator *res_alloc, | ||
368 | enum mlx4_resource res_type, | ||
369 | int vf, int num_instances) | ||
370 | { | ||
371 | res_alloc->guaranteed[vf] = num_instances / (2 * (dev->num_vfs + 1)); | ||
372 | res_alloc->quota[vf] = (num_instances / 2) + res_alloc->guaranteed[vf]; | ||
373 | if (vf == mlx4_master_func_num(dev)) { | ||
374 | res_alloc->res_free = num_instances; | ||
375 | if (res_type == RES_MTT) { | ||
376 | /* reserved mtts will be taken out of the PF allocation */ | ||
377 | res_alloc->res_free += dev->caps.reserved_mtts; | ||
378 | res_alloc->guaranteed[vf] += dev->caps.reserved_mtts; | ||
379 | res_alloc->quota[vf] += dev->caps.reserved_mtts; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | void mlx4_init_quotas(struct mlx4_dev *dev) | ||
385 | { | ||
386 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
387 | int pf; | ||
388 | |||
389 | /* quotas for VFs are initialized in mlx4_slave_cap */ | ||
390 | if (mlx4_is_slave(dev)) | ||
391 | return; | ||
392 | |||
393 | if (!mlx4_is_mfunc(dev)) { | ||
394 | dev->quotas.qp = dev->caps.num_qps - dev->caps.reserved_qps - | ||
395 | mlx4_num_reserved_sqps(dev); | ||
396 | dev->quotas.cq = dev->caps.num_cqs - dev->caps.reserved_cqs; | ||
397 | dev->quotas.srq = dev->caps.num_srqs - dev->caps.reserved_srqs; | ||
398 | dev->quotas.mtt = dev->caps.num_mtts - dev->caps.reserved_mtts; | ||
399 | dev->quotas.mpt = dev->caps.num_mpts - dev->caps.reserved_mrws; | ||
400 | return; | ||
401 | } | ||
402 | |||
403 | pf = mlx4_master_func_num(dev); | ||
404 | dev->quotas.qp = | ||
405 | priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[pf]; | ||
406 | dev->quotas.cq = | ||
407 | priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[pf]; | ||
408 | dev->quotas.srq = | ||
409 | priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[pf]; | ||
410 | dev->quotas.mtt = | ||
411 | priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[pf]; | ||
412 | dev->quotas.mpt = | ||
413 | priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf]; | ||
414 | } | ||
277 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) | 415 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) |
278 | { | 416 | { |
279 | struct mlx4_priv *priv = mlx4_priv(dev); | 417 | struct mlx4_priv *priv = mlx4_priv(dev); |
280 | int i; | 418 | int i, j; |
281 | int t; | 419 | int t; |
282 | 420 | ||
283 | priv->mfunc.master.res_tracker.slave_list = | 421 | priv->mfunc.master.res_tracker.slave_list = |
@@ -298,8 +436,105 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) | |||
298 | for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) | 436 | for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) |
299 | priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT; | 437 | priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT; |
300 | 438 | ||
439 | for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) { | ||
440 | struct resource_allocator *res_alloc = | ||
441 | &priv->mfunc.master.res_tracker.res_alloc[i]; | ||
442 | res_alloc->quota = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL); | ||
443 | res_alloc->guaranteed = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL); | ||
444 | if (i == RES_MAC || i == RES_VLAN) | ||
445 | res_alloc->allocated = kzalloc(MLX4_MAX_PORTS * | ||
446 | (dev->num_vfs + 1) * sizeof(int), | ||
447 | GFP_KERNEL); | ||
448 | else | ||
449 | res_alloc->allocated = kzalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL); | ||
450 | |||
451 | if (!res_alloc->quota || !res_alloc->guaranteed || | ||
452 | !res_alloc->allocated) | ||
453 | goto no_mem_err; | ||
454 | |||
455 | spin_lock_init(&res_alloc->alloc_lock); | ||
456 | for (t = 0; t < dev->num_vfs + 1; t++) { | ||
457 | switch (i) { | ||
458 | case RES_QP: | ||
459 | initialize_res_quotas(dev, res_alloc, RES_QP, | ||
460 | t, dev->caps.num_qps - | ||
461 | dev->caps.reserved_qps - | ||
462 | mlx4_num_reserved_sqps(dev)); | ||
463 | break; | ||
464 | case RES_CQ: | ||
465 | initialize_res_quotas(dev, res_alloc, RES_CQ, | ||
466 | t, dev->caps.num_cqs - | ||
467 | dev->caps.reserved_cqs); | ||
468 | break; | ||
469 | case RES_SRQ: | ||
470 | initialize_res_quotas(dev, res_alloc, RES_SRQ, | ||
471 | t, dev->caps.num_srqs - | ||
472 | dev->caps.reserved_srqs); | ||
473 | break; | ||
474 | case RES_MPT: | ||
475 | initialize_res_quotas(dev, res_alloc, RES_MPT, | ||
476 | t, dev->caps.num_mpts - | ||
477 | dev->caps.reserved_mrws); | ||
478 | break; | ||
479 | case RES_MTT: | ||
480 | initialize_res_quotas(dev, res_alloc, RES_MTT, | ||
481 | t, dev->caps.num_mtts - | ||
482 | dev->caps.reserved_mtts); | ||
483 | break; | ||
484 | case RES_MAC: | ||
485 | if (t == mlx4_master_func_num(dev)) { | ||
486 | res_alloc->quota[t] = MLX4_MAX_MAC_NUM; | ||
487 | res_alloc->guaranteed[t] = 2; | ||
488 | for (j = 0; j < MLX4_MAX_PORTS; j++) | ||
489 | res_alloc->res_port_free[j] = MLX4_MAX_MAC_NUM; | ||
490 | } else { | ||
491 | res_alloc->quota[t] = MLX4_MAX_MAC_NUM; | ||
492 | res_alloc->guaranteed[t] = 2; | ||
493 | } | ||
494 | break; | ||
495 | case RES_VLAN: | ||
496 | if (t == mlx4_master_func_num(dev)) { | ||
497 | res_alloc->quota[t] = MLX4_MAX_VLAN_NUM; | ||
498 | res_alloc->guaranteed[t] = MLX4_MAX_VLAN_NUM / 2; | ||
499 | for (j = 0; j < MLX4_MAX_PORTS; j++) | ||
500 | res_alloc->res_port_free[j] = | ||
501 | res_alloc->quota[t]; | ||
502 | } else { | ||
503 | res_alloc->quota[t] = MLX4_MAX_VLAN_NUM / 2; | ||
504 | res_alloc->guaranteed[t] = 0; | ||
505 | } | ||
506 | break; | ||
507 | case RES_COUNTER: | ||
508 | res_alloc->quota[t] = dev->caps.max_counters; | ||
509 | res_alloc->guaranteed[t] = 0; | ||
510 | if (t == mlx4_master_func_num(dev)) | ||
511 | res_alloc->res_free = res_alloc->quota[t]; | ||
512 | break; | ||
513 | default: | ||
514 | break; | ||
515 | } | ||
516 | if (i == RES_MAC || i == RES_VLAN) { | ||
517 | for (j = 0; j < MLX4_MAX_PORTS; j++) | ||
518 | res_alloc->res_port_rsvd[j] += | ||
519 | res_alloc->guaranteed[t]; | ||
520 | } else { | ||
521 | res_alloc->res_reserved += res_alloc->guaranteed[t]; | ||
522 | } | ||
523 | } | ||
524 | } | ||
301 | spin_lock_init(&priv->mfunc.master.res_tracker.lock); | 525 | spin_lock_init(&priv->mfunc.master.res_tracker.lock); |
302 | return 0 ; | 526 | return 0; |
527 | |||
528 | no_mem_err: | ||
529 | for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) { | ||
530 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated); | ||
531 | priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL; | ||
532 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed); | ||
533 | priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL; | ||
534 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota); | ||
535 | priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL; | ||
536 | } | ||
537 | return -ENOMEM; | ||
303 | } | 538 | } |
304 | 539 | ||
305 | void mlx4_free_resource_tracker(struct mlx4_dev *dev, | 540 | void mlx4_free_resource_tracker(struct mlx4_dev *dev, |
@@ -309,13 +544,28 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev, | |||
309 | int i; | 544 | int i; |
310 | 545 | ||
311 | if (priv->mfunc.master.res_tracker.slave_list) { | 546 | if (priv->mfunc.master.res_tracker.slave_list) { |
312 | if (type != RES_TR_FREE_STRUCTS_ONLY) | 547 | if (type != RES_TR_FREE_STRUCTS_ONLY) { |
313 | for (i = 0 ; i < dev->num_slaves; i++) | 548 | for (i = 0; i < dev->num_slaves; i++) { |
314 | if (type == RES_TR_FREE_ALL || | 549 | if (type == RES_TR_FREE_ALL || |
315 | dev->caps.function != i) | 550 | dev->caps.function != i) |
316 | mlx4_delete_all_resources_for_slave(dev, i); | 551 | mlx4_delete_all_resources_for_slave(dev, i); |
552 | } | ||
553 | /* free master's vlans */ | ||
554 | i = dev->caps.function; | ||
555 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); | ||
556 | rem_slave_vlans(dev, i); | ||
557 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); | ||
558 | } | ||
317 | 559 | ||
318 | if (type != RES_TR_FREE_SLAVES_ONLY) { | 560 | if (type != RES_TR_FREE_SLAVES_ONLY) { |
561 | for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) { | ||
562 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated); | ||
563 | priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL; | ||
564 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed); | ||
565 | priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL; | ||
566 | kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota); | ||
567 | priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL; | ||
568 | } | ||
319 | kfree(priv->mfunc.master.res_tracker.slave_list); | 569 | kfree(priv->mfunc.master.res_tracker.slave_list); |
320 | priv->mfunc.master.res_tracker.slave_list = NULL; | 570 | priv->mfunc.master.res_tracker.slave_list = NULL; |
321 | } | 571 | } |
@@ -1229,12 +1479,19 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1229 | case RES_OP_RESERVE: | 1479 | case RES_OP_RESERVE: |
1230 | count = get_param_l(&in_param); | 1480 | count = get_param_l(&in_param); |
1231 | align = get_param_h(&in_param); | 1481 | align = get_param_h(&in_param); |
1232 | err = __mlx4_qp_reserve_range(dev, count, align, &base); | 1482 | err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); |
1233 | if (err) | 1483 | if (err) |
1234 | return err; | 1484 | return err; |
1235 | 1485 | ||
1486 | err = __mlx4_qp_reserve_range(dev, count, align, &base); | ||
1487 | if (err) { | ||
1488 | mlx4_release_resource(dev, slave, RES_QP, count, 0); | ||
1489 | return err; | ||
1490 | } | ||
1491 | |||
1236 | err = add_res_range(dev, slave, base, count, RES_QP, 0); | 1492 | err = add_res_range(dev, slave, base, count, RES_QP, 0); |
1237 | if (err) { | 1493 | if (err) { |
1494 | mlx4_release_resource(dev, slave, RES_QP, count, 0); | ||
1238 | __mlx4_qp_release_range(dev, base, count); | 1495 | __mlx4_qp_release_range(dev, base, count); |
1239 | return err; | 1496 | return err; |
1240 | } | 1497 | } |
@@ -1282,15 +1539,24 @@ static int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1282 | return err; | 1539 | return err; |
1283 | 1540 | ||
1284 | order = get_param_l(&in_param); | 1541 | order = get_param_l(&in_param); |
1542 | |||
1543 | err = mlx4_grant_resource(dev, slave, RES_MTT, 1 << order, 0); | ||
1544 | if (err) | ||
1545 | return err; | ||
1546 | |||
1285 | base = __mlx4_alloc_mtt_range(dev, order); | 1547 | base = __mlx4_alloc_mtt_range(dev, order); |
1286 | if (base == -1) | 1548 | if (base == -1) { |
1549 | mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0); | ||
1287 | return -ENOMEM; | 1550 | return -ENOMEM; |
1551 | } | ||
1288 | 1552 | ||
1289 | err = add_res_range(dev, slave, base, 1, RES_MTT, order); | 1553 | err = add_res_range(dev, slave, base, 1, RES_MTT, order); |
1290 | if (err) | 1554 | if (err) { |
1555 | mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0); | ||
1291 | __mlx4_free_mtt_range(dev, base, order); | 1556 | __mlx4_free_mtt_range(dev, base, order); |
1292 | else | 1557 | } else { |
1293 | set_param_l(out_param, base); | 1558 | set_param_l(out_param, base); |
1559 | } | ||
1294 | 1560 | ||
1295 | return err; | 1561 | return err; |
1296 | } | 1562 | } |
@@ -1305,13 +1571,20 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1305 | 1571 | ||
1306 | switch (op) { | 1572 | switch (op) { |
1307 | case RES_OP_RESERVE: | 1573 | case RES_OP_RESERVE: |
1574 | err = mlx4_grant_resource(dev, slave, RES_MPT, 1, 0); | ||
1575 | if (err) | ||
1576 | break; | ||
1577 | |||
1308 | index = __mlx4_mpt_reserve(dev); | 1578 | index = __mlx4_mpt_reserve(dev); |
1309 | if (index == -1) | 1579 | if (index == -1) { |
1580 | mlx4_release_resource(dev, slave, RES_MPT, 1, 0); | ||
1310 | break; | 1581 | break; |
1582 | } | ||
1311 | id = index & mpt_mask(dev); | 1583 | id = index & mpt_mask(dev); |
1312 | 1584 | ||
1313 | err = add_res_range(dev, slave, id, 1, RES_MPT, index); | 1585 | err = add_res_range(dev, slave, id, 1, RES_MPT, index); |
1314 | if (err) { | 1586 | if (err) { |
1587 | mlx4_release_resource(dev, slave, RES_MPT, 1, 0); | ||
1315 | __mlx4_mpt_release(dev, index); | 1588 | __mlx4_mpt_release(dev, index); |
1316 | break; | 1589 | break; |
1317 | } | 1590 | } |
@@ -1345,12 +1618,19 @@ static int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1345 | 1618 | ||
1346 | switch (op) { | 1619 | switch (op) { |
1347 | case RES_OP_RESERVE_AND_MAP: | 1620 | case RES_OP_RESERVE_AND_MAP: |
1348 | err = __mlx4_cq_alloc_icm(dev, &cqn); | 1621 | err = mlx4_grant_resource(dev, slave, RES_CQ, 1, 0); |
1349 | if (err) | 1622 | if (err) |
1350 | break; | 1623 | break; |
1351 | 1624 | ||
1625 | err = __mlx4_cq_alloc_icm(dev, &cqn); | ||
1626 | if (err) { | ||
1627 | mlx4_release_resource(dev, slave, RES_CQ, 1, 0); | ||
1628 | break; | ||
1629 | } | ||
1630 | |||
1352 | err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0); | 1631 | err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0); |
1353 | if (err) { | 1632 | if (err) { |
1633 | mlx4_release_resource(dev, slave, RES_CQ, 1, 0); | ||
1354 | __mlx4_cq_free_icm(dev, cqn); | 1634 | __mlx4_cq_free_icm(dev, cqn); |
1355 | break; | 1635 | break; |
1356 | } | 1636 | } |
@@ -1373,12 +1653,19 @@ static int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1373 | 1653 | ||
1374 | switch (op) { | 1654 | switch (op) { |
1375 | case RES_OP_RESERVE_AND_MAP: | 1655 | case RES_OP_RESERVE_AND_MAP: |
1376 | err = __mlx4_srq_alloc_icm(dev, &srqn); | 1656 | err = mlx4_grant_resource(dev, slave, RES_SRQ, 1, 0); |
1377 | if (err) | 1657 | if (err) |
1378 | break; | 1658 | break; |
1379 | 1659 | ||
1660 | err = __mlx4_srq_alloc_icm(dev, &srqn); | ||
1661 | if (err) { | ||
1662 | mlx4_release_resource(dev, slave, RES_SRQ, 1, 0); | ||
1663 | break; | ||
1664 | } | ||
1665 | |||
1380 | err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0); | 1666 | err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0); |
1381 | if (err) { | 1667 | if (err) { |
1668 | mlx4_release_resource(dev, slave, RES_SRQ, 1, 0); | ||
1382 | __mlx4_srq_free_icm(dev, srqn); | 1669 | __mlx4_srq_free_icm(dev, srqn); |
1383 | break; | 1670 | break; |
1384 | } | 1671 | } |
@@ -1399,9 +1686,13 @@ static int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port) | |||
1399 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | 1686 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; |
1400 | struct mac_res *res; | 1687 | struct mac_res *res; |
1401 | 1688 | ||
1689 | if (mlx4_grant_resource(dev, slave, RES_MAC, 1, port)) | ||
1690 | return -EINVAL; | ||
1402 | res = kzalloc(sizeof *res, GFP_KERNEL); | 1691 | res = kzalloc(sizeof *res, GFP_KERNEL); |
1403 | if (!res) | 1692 | if (!res) { |
1693 | mlx4_release_resource(dev, slave, RES_MAC, 1, port); | ||
1404 | return -ENOMEM; | 1694 | return -ENOMEM; |
1695 | } | ||
1405 | res->mac = mac; | 1696 | res->mac = mac; |
1406 | res->port = (u8) port; | 1697 | res->port = (u8) port; |
1407 | list_add_tail(&res->list, | 1698 | list_add_tail(&res->list, |
@@ -1421,6 +1712,7 @@ static void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac, | |||
1421 | list_for_each_entry_safe(res, tmp, mac_list, list) { | 1712 | list_for_each_entry_safe(res, tmp, mac_list, list) { |
1422 | if (res->mac == mac && res->port == (u8) port) { | 1713 | if (res->mac == mac && res->port == (u8) port) { |
1423 | list_del(&res->list); | 1714 | list_del(&res->list); |
1715 | mlx4_release_resource(dev, slave, RES_MAC, 1, port); | ||
1424 | kfree(res); | 1716 | kfree(res); |
1425 | break; | 1717 | break; |
1426 | } | 1718 | } |
@@ -1438,12 +1730,13 @@ static void rem_slave_macs(struct mlx4_dev *dev, int slave) | |||
1438 | list_for_each_entry_safe(res, tmp, mac_list, list) { | 1730 | list_for_each_entry_safe(res, tmp, mac_list, list) { |
1439 | list_del(&res->list); | 1731 | list_del(&res->list); |
1440 | __mlx4_unregister_mac(dev, res->port, res->mac); | 1732 | __mlx4_unregister_mac(dev, res->port, res->mac); |
1733 | mlx4_release_resource(dev, slave, RES_MAC, 1, res->port); | ||
1441 | kfree(res); | 1734 | kfree(res); |
1442 | } | 1735 | } |
1443 | } | 1736 | } |
1444 | 1737 | ||
1445 | static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1738 | static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1446 | u64 in_param, u64 *out_param) | 1739 | u64 in_param, u64 *out_param, int in_port) |
1447 | { | 1740 | { |
1448 | int err = -EINVAL; | 1741 | int err = -EINVAL; |
1449 | int port; | 1742 | int port; |
@@ -1452,7 +1745,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1452 | if (op != RES_OP_RESERVE_AND_MAP) | 1745 | if (op != RES_OP_RESERVE_AND_MAP) |
1453 | return err; | 1746 | return err; |
1454 | 1747 | ||
1455 | port = get_param_l(out_param); | 1748 | port = !in_port ? get_param_l(out_param) : in_port; |
1456 | mac = in_param; | 1749 | mac = in_param; |
1457 | 1750 | ||
1458 | err = __mlx4_register_mac(dev, port, mac); | 1751 | err = __mlx4_register_mac(dev, port, mac); |
@@ -1469,12 +1762,114 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1469 | return err; | 1762 | return err; |
1470 | } | 1763 | } |
1471 | 1764 | ||
1472 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1765 | static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan, |
1473 | u64 in_param, u64 *out_param) | 1766 | int port, int vlan_index) |
1474 | { | 1767 | { |
1768 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1769 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1770 | struct list_head *vlan_list = | ||
1771 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1772 | struct vlan_res *res, *tmp; | ||
1773 | |||
1774 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1775 | if (res->vlan == vlan && res->port == (u8) port) { | ||
1776 | /* vlan found. update ref count */ | ||
1777 | ++res->ref_count; | ||
1778 | return 0; | ||
1779 | } | ||
1780 | } | ||
1781 | |||
1782 | if (mlx4_grant_resource(dev, slave, RES_VLAN, 1, port)) | ||
1783 | return -EINVAL; | ||
1784 | res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
1785 | if (!res) { | ||
1786 | mlx4_release_resource(dev, slave, RES_VLAN, 1, port); | ||
1787 | return -ENOMEM; | ||
1788 | } | ||
1789 | res->vlan = vlan; | ||
1790 | res->port = (u8) port; | ||
1791 | res->vlan_index = vlan_index; | ||
1792 | res->ref_count = 1; | ||
1793 | list_add_tail(&res->list, | ||
1794 | &tracker->slave_list[slave].res_list[RES_VLAN]); | ||
1475 | return 0; | 1795 | return 0; |
1476 | } | 1796 | } |
1477 | 1797 | ||
1798 | |||
1799 | static void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan, | ||
1800 | int port) | ||
1801 | { | ||
1802 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1803 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1804 | struct list_head *vlan_list = | ||
1805 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1806 | struct vlan_res *res, *tmp; | ||
1807 | |||
1808 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1809 | if (res->vlan == vlan && res->port == (u8) port) { | ||
1810 | if (!--res->ref_count) { | ||
1811 | list_del(&res->list); | ||
1812 | mlx4_release_resource(dev, slave, RES_VLAN, | ||
1813 | 1, port); | ||
1814 | kfree(res); | ||
1815 | } | ||
1816 | break; | ||
1817 | } | ||
1818 | } | ||
1819 | } | ||
1820 | |||
1821 | static void rem_slave_vlans(struct mlx4_dev *dev, int slave) | ||
1822 | { | ||
1823 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1824 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1825 | struct list_head *vlan_list = | ||
1826 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1827 | struct vlan_res *res, *tmp; | ||
1828 | int i; | ||
1829 | |||
1830 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1831 | list_del(&res->list); | ||
1832 | /* dereference the vlan the num times the slave referenced it */ | ||
1833 | for (i = 0; i < res->ref_count; i++) | ||
1834 | __mlx4_unregister_vlan(dev, res->port, res->vlan); | ||
1835 | mlx4_release_resource(dev, slave, RES_VLAN, 1, res->port); | ||
1836 | kfree(res); | ||
1837 | } | ||
1838 | } | ||
1839 | |||
1840 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | ||
1841 | u64 in_param, u64 *out_param, int in_port) | ||
1842 | { | ||
1843 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1844 | struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; | ||
1845 | int err; | ||
1846 | u16 vlan; | ||
1847 | int vlan_index; | ||
1848 | int port; | ||
1849 | |||
1850 | port = !in_port ? get_param_l(out_param) : in_port; | ||
1851 | |||
1852 | if (!port || op != RES_OP_RESERVE_AND_MAP) | ||
1853 | return -EINVAL; | ||
1854 | |||
1855 | /* upstream kernels had NOP for reg/unreg vlan. Continue this. */ | ||
1856 | if (!in_port && port > 0 && port <= dev->caps.num_ports) { | ||
1857 | slave_state[slave].old_vlan_api = true; | ||
1858 | return 0; | ||
1859 | } | ||
1860 | |||
1861 | vlan = (u16) in_param; | ||
1862 | |||
1863 | err = __mlx4_register_vlan(dev, port, vlan, &vlan_index); | ||
1864 | if (!err) { | ||
1865 | set_param_l(out_param, (u32) vlan_index); | ||
1866 | err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index); | ||
1867 | if (err) | ||
1868 | __mlx4_unregister_vlan(dev, port, vlan); | ||
1869 | } | ||
1870 | return err; | ||
1871 | } | ||
1872 | |||
1478 | static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1873 | static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1479 | u64 in_param, u64 *out_param) | 1874 | u64 in_param, u64 *out_param) |
1480 | { | 1875 | { |
@@ -1484,15 +1879,23 @@ static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1484 | if (op != RES_OP_RESERVE) | 1879 | if (op != RES_OP_RESERVE) |
1485 | return -EINVAL; | 1880 | return -EINVAL; |
1486 | 1881 | ||
1487 | err = __mlx4_counter_alloc(dev, &index); | 1882 | err = mlx4_grant_resource(dev, slave, RES_COUNTER, 1, 0); |
1488 | if (err) | 1883 | if (err) |
1489 | return err; | 1884 | return err; |
1490 | 1885 | ||
1886 | err = __mlx4_counter_alloc(dev, &index); | ||
1887 | if (err) { | ||
1888 | mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0); | ||
1889 | return err; | ||
1890 | } | ||
1891 | |||
1491 | err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0); | 1892 | err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0); |
1492 | if (err) | 1893 | if (err) { |
1493 | __mlx4_counter_free(dev, index); | 1894 | __mlx4_counter_free(dev, index); |
1494 | else | 1895 | mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0); |
1896 | } else { | ||
1495 | set_param_l(out_param, index); | 1897 | set_param_l(out_param, index); |
1898 | } | ||
1496 | 1899 | ||
1497 | return err; | 1900 | return err; |
1498 | } | 1901 | } |
@@ -1528,7 +1931,7 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1528 | int err; | 1931 | int err; |
1529 | int alop = vhcr->op_modifier; | 1932 | int alop = vhcr->op_modifier; |
1530 | 1933 | ||
1531 | switch (vhcr->in_modifier) { | 1934 | switch (vhcr->in_modifier & 0xFF) { |
1532 | case RES_QP: | 1935 | case RES_QP: |
1533 | err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, | 1936 | err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, |
1534 | vhcr->in_param, &vhcr->out_param); | 1937 | vhcr->in_param, &vhcr->out_param); |
@@ -1556,12 +1959,14 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1556 | 1959 | ||
1557 | case RES_MAC: | 1960 | case RES_MAC: |
1558 | err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, | 1961 | err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, |
1559 | vhcr->in_param, &vhcr->out_param); | 1962 | vhcr->in_param, &vhcr->out_param, |
1963 | (vhcr->in_modifier >> 8) & 0xFF); | ||
1560 | break; | 1964 | break; |
1561 | 1965 | ||
1562 | case RES_VLAN: | 1966 | case RES_VLAN: |
1563 | err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, | 1967 | err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, |
1564 | vhcr->in_param, &vhcr->out_param); | 1968 | vhcr->in_param, &vhcr->out_param, |
1969 | (vhcr->in_modifier >> 8) & 0xFF); | ||
1565 | break; | 1970 | break; |
1566 | 1971 | ||
1567 | case RES_COUNTER: | 1972 | case RES_COUNTER: |
@@ -1597,6 +2002,7 @@ static int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1597 | err = rem_res_range(dev, slave, base, count, RES_QP, 0); | 2002 | err = rem_res_range(dev, slave, base, count, RES_QP, 0); |
1598 | if (err) | 2003 | if (err) |
1599 | break; | 2004 | break; |
2005 | mlx4_release_resource(dev, slave, RES_QP, count, 0); | ||
1600 | __mlx4_qp_release_range(dev, base, count); | 2006 | __mlx4_qp_release_range(dev, base, count); |
1601 | break; | 2007 | break; |
1602 | case RES_OP_MAP_ICM: | 2008 | case RES_OP_MAP_ICM: |
@@ -1634,8 +2040,10 @@ static int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1634 | base = get_param_l(&in_param); | 2040 | base = get_param_l(&in_param); |
1635 | order = get_param_h(&in_param); | 2041 | order = get_param_h(&in_param); |
1636 | err = rem_res_range(dev, slave, base, 1, RES_MTT, order); | 2042 | err = rem_res_range(dev, slave, base, 1, RES_MTT, order); |
1637 | if (!err) | 2043 | if (!err) { |
2044 | mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0); | ||
1638 | __mlx4_free_mtt_range(dev, base, order); | 2045 | __mlx4_free_mtt_range(dev, base, order); |
2046 | } | ||
1639 | return err; | 2047 | return err; |
1640 | } | 2048 | } |
1641 | 2049 | ||
@@ -1660,6 +2068,7 @@ static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1660 | err = rem_res_range(dev, slave, id, 1, RES_MPT, 0); | 2068 | err = rem_res_range(dev, slave, id, 1, RES_MPT, 0); |
1661 | if (err) | 2069 | if (err) |
1662 | break; | 2070 | break; |
2071 | mlx4_release_resource(dev, slave, RES_MPT, 1, 0); | ||
1663 | __mlx4_mpt_release(dev, index); | 2072 | __mlx4_mpt_release(dev, index); |
1664 | break; | 2073 | break; |
1665 | case RES_OP_MAP_ICM: | 2074 | case RES_OP_MAP_ICM: |
@@ -1694,6 +2103,7 @@ static int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1694 | if (err) | 2103 | if (err) |
1695 | break; | 2104 | break; |
1696 | 2105 | ||
2106 | mlx4_release_resource(dev, slave, RES_CQ, 1, 0); | ||
1697 | __mlx4_cq_free_icm(dev, cqn); | 2107 | __mlx4_cq_free_icm(dev, cqn); |
1698 | break; | 2108 | break; |
1699 | 2109 | ||
@@ -1718,6 +2128,7 @@ static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1718 | if (err) | 2128 | if (err) |
1719 | break; | 2129 | break; |
1720 | 2130 | ||
2131 | mlx4_release_resource(dev, slave, RES_SRQ, 1, 0); | ||
1721 | __mlx4_srq_free_icm(dev, srqn); | 2132 | __mlx4_srq_free_icm(dev, srqn); |
1722 | break; | 2133 | break; |
1723 | 2134 | ||
@@ -1730,14 +2141,14 @@ static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1730 | } | 2141 | } |
1731 | 2142 | ||
1732 | static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 2143 | static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1733 | u64 in_param, u64 *out_param) | 2144 | u64 in_param, u64 *out_param, int in_port) |
1734 | { | 2145 | { |
1735 | int port; | 2146 | int port; |
1736 | int err = 0; | 2147 | int err = 0; |
1737 | 2148 | ||
1738 | switch (op) { | 2149 | switch (op) { |
1739 | case RES_OP_RESERVE_AND_MAP: | 2150 | case RES_OP_RESERVE_AND_MAP: |
1740 | port = get_param_l(out_param); | 2151 | port = !in_port ? get_param_l(out_param) : in_port; |
1741 | mac_del_from_slave(dev, slave, in_param, port); | 2152 | mac_del_from_slave(dev, slave, in_param, port); |
1742 | __mlx4_unregister_mac(dev, port, in_param); | 2153 | __mlx4_unregister_mac(dev, port, in_param); |
1743 | break; | 2154 | break; |
@@ -1751,9 +2162,27 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1751 | } | 2162 | } |
1752 | 2163 | ||
1753 | static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 2164 | static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1754 | u64 in_param, u64 *out_param) | 2165 | u64 in_param, u64 *out_param, int port) |
1755 | { | 2166 | { |
1756 | return 0; | 2167 | struct mlx4_priv *priv = mlx4_priv(dev); |
2168 | struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; | ||
2169 | int err = 0; | ||
2170 | |||
2171 | switch (op) { | ||
2172 | case RES_OP_RESERVE_AND_MAP: | ||
2173 | if (slave_state[slave].old_vlan_api) | ||
2174 | return 0; | ||
2175 | if (!port) | ||
2176 | return -EINVAL; | ||
2177 | vlan_del_from_slave(dev, slave, in_param, port); | ||
2178 | __mlx4_unregister_vlan(dev, port, in_param); | ||
2179 | break; | ||
2180 | default: | ||
2181 | err = -EINVAL; | ||
2182 | break; | ||
2183 | } | ||
2184 | |||
2185 | return err; | ||
1757 | } | 2186 | } |
1758 | 2187 | ||
1759 | static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 2188 | static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
@@ -1771,6 +2200,7 @@ static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1771 | return err; | 2200 | return err; |
1772 | 2201 | ||
1773 | __mlx4_counter_free(dev, index); | 2202 | __mlx4_counter_free(dev, index); |
2203 | mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0); | ||
1774 | 2204 | ||
1775 | return err; | 2205 | return err; |
1776 | } | 2206 | } |
@@ -1803,7 +2233,7 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1803 | int err = -EINVAL; | 2233 | int err = -EINVAL; |
1804 | int alop = vhcr->op_modifier; | 2234 | int alop = vhcr->op_modifier; |
1805 | 2235 | ||
1806 | switch (vhcr->in_modifier) { | 2236 | switch (vhcr->in_modifier & 0xFF) { |
1807 | case RES_QP: | 2237 | case RES_QP: |
1808 | err = qp_free_res(dev, slave, vhcr->op_modifier, alop, | 2238 | err = qp_free_res(dev, slave, vhcr->op_modifier, alop, |
1809 | vhcr->in_param); | 2239 | vhcr->in_param); |
@@ -1831,12 +2261,14 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1831 | 2261 | ||
1832 | case RES_MAC: | 2262 | case RES_MAC: |
1833 | err = mac_free_res(dev, slave, vhcr->op_modifier, alop, | 2263 | err = mac_free_res(dev, slave, vhcr->op_modifier, alop, |
1834 | vhcr->in_param, &vhcr->out_param); | 2264 | vhcr->in_param, &vhcr->out_param, |
2265 | (vhcr->in_modifier >> 8) & 0xFF); | ||
1835 | break; | 2266 | break; |
1836 | 2267 | ||
1837 | case RES_VLAN: | 2268 | case RES_VLAN: |
1838 | err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, | 2269 | err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, |
1839 | vhcr->in_param, &vhcr->out_param); | 2270 | vhcr->in_param, &vhcr->out_param, |
2271 | (vhcr->in_modifier >> 8) & 0xFF); | ||
1840 | break; | 2272 | break; |
1841 | 2273 | ||
1842 | case RES_COUNTER: | 2274 | case RES_COUNTER: |
@@ -3498,6 +3930,11 @@ static void rem_slave_qps(struct mlx4_dev *dev, int slave) | |||
3498 | &tracker->res_tree[RES_QP]); | 3930 | &tracker->res_tree[RES_QP]); |
3499 | list_del(&qp->com.list); | 3931 | list_del(&qp->com.list); |
3500 | spin_unlock_irq(mlx4_tlock(dev)); | 3932 | spin_unlock_irq(mlx4_tlock(dev)); |
3933 | if (!valid_reserved(dev, slave, qpn)) { | ||
3934 | __mlx4_qp_release_range(dev, qpn, 1); | ||
3935 | mlx4_release_resource(dev, slave, | ||
3936 | RES_QP, 1, 0); | ||
3937 | } | ||
3501 | kfree(qp); | 3938 | kfree(qp); |
3502 | state = 0; | 3939 | state = 0; |
3503 | break; | 3940 | break; |
@@ -3569,6 +4006,8 @@ static void rem_slave_srqs(struct mlx4_dev *dev, int slave) | |||
3569 | &tracker->res_tree[RES_SRQ]); | 4006 | &tracker->res_tree[RES_SRQ]); |
3570 | list_del(&srq->com.list); | 4007 | list_del(&srq->com.list); |
3571 | spin_unlock_irq(mlx4_tlock(dev)); | 4008 | spin_unlock_irq(mlx4_tlock(dev)); |
4009 | mlx4_release_resource(dev, slave, | ||
4010 | RES_SRQ, 1, 0); | ||
3572 | kfree(srq); | 4011 | kfree(srq); |
3573 | state = 0; | 4012 | state = 0; |
3574 | break; | 4013 | break; |
@@ -3635,6 +4074,8 @@ static void rem_slave_cqs(struct mlx4_dev *dev, int slave) | |||
3635 | &tracker->res_tree[RES_CQ]); | 4074 | &tracker->res_tree[RES_CQ]); |
3636 | list_del(&cq->com.list); | 4075 | list_del(&cq->com.list); |
3637 | spin_unlock_irq(mlx4_tlock(dev)); | 4076 | spin_unlock_irq(mlx4_tlock(dev)); |
4077 | mlx4_release_resource(dev, slave, | ||
4078 | RES_CQ, 1, 0); | ||
3638 | kfree(cq); | 4079 | kfree(cq); |
3639 | state = 0; | 4080 | state = 0; |
3640 | break; | 4081 | break; |
@@ -3698,6 +4139,8 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave) | |||
3698 | &tracker->res_tree[RES_MPT]); | 4139 | &tracker->res_tree[RES_MPT]); |
3699 | list_del(&mpt->com.list); | 4140 | list_del(&mpt->com.list); |
3700 | spin_unlock_irq(mlx4_tlock(dev)); | 4141 | spin_unlock_irq(mlx4_tlock(dev)); |
4142 | mlx4_release_resource(dev, slave, | ||
4143 | RES_MPT, 1, 0); | ||
3701 | kfree(mpt); | 4144 | kfree(mpt); |
3702 | state = 0; | 4145 | state = 0; |
3703 | break; | 4146 | break; |
@@ -3767,6 +4210,8 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave) | |||
3767 | &tracker->res_tree[RES_MTT]); | 4210 | &tracker->res_tree[RES_MTT]); |
3768 | list_del(&mtt->com.list); | 4211 | list_del(&mtt->com.list); |
3769 | spin_unlock_irq(mlx4_tlock(dev)); | 4212 | spin_unlock_irq(mlx4_tlock(dev)); |
4213 | mlx4_release_resource(dev, slave, RES_MTT, | ||
4214 | 1 << mtt->order, 0); | ||
3770 | kfree(mtt); | 4215 | kfree(mtt); |
3771 | state = 0; | 4216 | state = 0; |
3772 | break; | 4217 | break; |
@@ -3925,6 +4370,7 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave) | |||
3925 | list_del(&counter->com.list); | 4370 | list_del(&counter->com.list); |
3926 | kfree(counter); | 4371 | kfree(counter); |
3927 | __mlx4_counter_free(dev, index); | 4372 | __mlx4_counter_free(dev, index); |
4373 | mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0); | ||
3928 | } | 4374 | } |
3929 | } | 4375 | } |
3930 | spin_unlock_irq(mlx4_tlock(dev)); | 4376 | spin_unlock_irq(mlx4_tlock(dev)); |
@@ -3964,7 +4410,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
3964 | struct mlx4_priv *priv = mlx4_priv(dev); | 4410 | struct mlx4_priv *priv = mlx4_priv(dev); |
3965 | 4411 | ||
3966 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 4412 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
3967 | /*VLAN*/ | 4413 | rem_slave_vlans(dev, slave); |
3968 | rem_slave_macs(dev, slave); | 4414 | rem_slave_macs(dev, slave); |
3969 | rem_slave_fs_rule(dev, slave); | 4415 | rem_slave_fs_rule(dev, slave); |
3970 | rem_slave_qps(dev, slave); | 4416 | rem_slave_qps(dev, slave); |
@@ -4081,7 +4527,7 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) | |||
4081 | if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors && | 4527 | if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors && |
4082 | NO_INDX != work->orig_vlan_ix) | 4528 | NO_INDX != work->orig_vlan_ix) |
4083 | __mlx4_unregister_vlan(&work->priv->dev, work->port, | 4529 | __mlx4_unregister_vlan(&work->priv->dev, work->port, |
4084 | work->orig_vlan_ix); | 4530 | work->orig_vlan_id); |
4085 | out: | 4531 | out: |
4086 | kfree(work); | 4532 | kfree(work); |
4087 | return; | 4533 | return; |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 9ad0c18495ad..f6f59271f857 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -54,6 +54,7 @@ enum { | |||
54 | MLX4_FLAG_MASTER = 1 << 2, | 54 | MLX4_FLAG_MASTER = 1 << 2, |
55 | MLX4_FLAG_SLAVE = 1 << 3, | 55 | MLX4_FLAG_SLAVE = 1 << 3, |
56 | MLX4_FLAG_SRIOV = 1 << 4, | 56 | MLX4_FLAG_SRIOV = 1 << 4, |
57 | MLX4_FLAG_OLD_REG_MAC = 1 << 6, | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | enum { | 60 | enum { |
@@ -640,12 +641,23 @@ struct mlx4_counter { | |||
640 | __be64 tx_bytes; | 641 | __be64 tx_bytes; |
641 | }; | 642 | }; |
642 | 643 | ||
644 | struct mlx4_quotas { | ||
645 | int qp; | ||
646 | int cq; | ||
647 | int srq; | ||
648 | int mpt; | ||
649 | int mtt; | ||
650 | int counter; | ||
651 | int xrcd; | ||
652 | }; | ||
653 | |||
643 | struct mlx4_dev { | 654 | struct mlx4_dev { |
644 | struct pci_dev *pdev; | 655 | struct pci_dev *pdev; |
645 | unsigned long flags; | 656 | unsigned long flags; |
646 | unsigned long num_slaves; | 657 | unsigned long num_slaves; |
647 | struct mlx4_caps caps; | 658 | struct mlx4_caps caps; |
648 | struct mlx4_phys_caps phys_caps; | 659 | struct mlx4_phys_caps phys_caps; |
660 | struct mlx4_quotas quotas; | ||
649 | struct radix_tree_root qp_table_tree; | 661 | struct radix_tree_root qp_table_tree; |
650 | u8 rev_id; | 662 | u8 rev_id; |
651 | char board_id[MLX4_BOARD_ID_LEN]; | 663 | char board_id[MLX4_BOARD_ID_LEN]; |
@@ -771,6 +783,12 @@ static inline int mlx4_is_master(struct mlx4_dev *dev) | |||
771 | return dev->flags & MLX4_FLAG_MASTER; | 783 | return dev->flags & MLX4_FLAG_MASTER; |
772 | } | 784 | } |
773 | 785 | ||
786 | static inline int mlx4_num_reserved_sqps(struct mlx4_dev *dev) | ||
787 | { | ||
788 | return dev->phys_caps.base_sqpn + 8 + | ||
789 | 16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev); | ||
790 | } | ||
791 | |||
774 | static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) | 792 | static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) |
775 | { | 793 | { |
776 | return (qpn < dev->phys_caps.base_sqpn + 8 + | 794 | return (qpn < dev->phys_caps.base_sqpn + 8 + |
@@ -1078,7 +1096,7 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, | |||
1078 | u8 *pg, u16 *ratelimit); | 1096 | u8 *pg, u16 *ratelimit); |
1079 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); | 1097 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); |
1080 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); | 1098 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); |
1081 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); | 1099 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); |
1082 | 1100 | ||
1083 | int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list, | 1101 | int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list, |
1084 | int npages, u64 iova, u32 *lkey, u32 *rkey); | 1102 | int npages, u64 iova, u32 *lkey, u32 *rkey); |