diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index 6c95d3cde..a5bc1aa3c 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -407,7 +407,8 @@ struct mqnic_if { struct mqnic_res *rxq_res; u32 eq_count; - struct mqnic_eq *eq[MQNIC_MAX_EQ]; + struct rw_semaphore eq_table_sem; + struct radix_tree_root eq_table; u32 port_count; struct mqnic_port *port[MQNIC_MAX_PORTS]; diff --git a/modules/mqnic/mqnic_if.c b/modules/mqnic/mqnic_if.c index 01d1e91c8..7884306b5 100644 --- a/modules/mqnic/mqnic_if.c +++ b/modules/mqnic/mqnic_if.c @@ -29,6 +29,9 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ interface->hw_addr = hw_addr; interface->csr_hw_addr = hw_addr + mdev->if_csr_offset; + init_rwsem(&interface->eq_table_sem); + INIT_RADIX_TREE(&interface->eq_table, GFP_KERNEL); + INIT_LIST_HEAD(&interface->free_sched_port_list); spin_lock_init(&interface->free_sched_port_list_lock); @@ -262,7 +265,13 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ goto fail; } - interface->eq[k] = eq; + down_write(&interface->eq_table_sem); + ret = radix_tree_insert(&interface->eq_table, k, eq); + up_write(&interface->eq_table_sem); + if (ret) { + mqnic_destroy_eq(eq); + goto fail; + } ret = mqnic_open_eq(eq, mdev->irq[k % mdev->irq_count], mqnic_num_eq_entries); if (ret) @@ -295,6 +304,8 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ void mqnic_destroy_interface(struct mqnic_if *interface) { struct mqnic_priv *priv, *priv_safe; + struct radix_tree_iter iter; + void **slot; int k; // destroy associated net_devices @@ -304,12 +315,12 @@ void mqnic_destroy_interface(struct mqnic_if *interface) } // free EQs - for (k = 0; k < ARRAY_SIZE(interface->eq); k++) { - if (interface->eq[k]) { - mqnic_destroy_eq(interface->eq[k]); - interface->eq[k] = NULL; - } + down_write(&interface->eq_table_sem); + radix_tree_for_each_slot(slot, &interface->eq_table, &iter, 0) { + struct mqnic_eq *eq = (struct mqnic_eq *)*slot; + mqnic_destroy_eq(eq); } + up_write(&interface->eq_table_sem); // free schedulers for (k = 0; k < ARRAY_SIZE(interface->sched_block); k++) { diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 6b5377c61..edcbc02ac 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -13,6 +13,7 @@ int mqnic_start_port(struct net_device *ndev) struct mqnic_if *iface = priv->interface; struct mqnic_ring *q; struct mqnic_cq *cq; + struct mqnic_eq *eq; struct radix_tree_iter iter; void **slot; int k; @@ -38,7 +39,11 @@ int mqnic_start_port(struct net_device *ndev) goto fail; } - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->rx_ring_size); + rcu_read_lock(); + eq = radix_tree_lookup(&iface->eq_table, k % iface->eq_count); + rcu_read_unlock(); + + ret = mqnic_open_cq(cq, eq, priv->rx_ring_size); if (ret) { mqnic_destroy_cq(cq); goto fail; @@ -93,7 +98,11 @@ int mqnic_start_port(struct net_device *ndev) goto fail; } - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->tx_ring_size); + rcu_read_lock(); + eq = radix_tree_lookup(&iface->eq_table, k % iface->eq_count); + rcu_read_unlock(); + + ret = mqnic_open_cq(cq, eq, priv->tx_ring_size); if (ret) { mqnic_destroy_cq(cq); goto fail;