diff options
author | Lendacky, Thomas <Thomas.Lendacky@amd.com> | 2014-11-04 17:06:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-05 21:50:11 -0500 |
commit | 4780b7cae60cf10af4ae75bc5d6643f41d4c2969 (patch) | |
tree | 1feb576159fdb1cbde6067336b83377f2ec8f93d | |
parent | 25de4668d094f00e44a8f2428dd3c1a4ecfa0053 (diff) |
amd-xgbe: Move ring allocation to device open
Move the channel and ring tracking structures allocation to device
open. This will allow for future support to vary the number of Tx/Rx
queues without unloading the module.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 93 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 62 |
3 files changed, 93 insertions, 70 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 2349ea970255..07b00bdcd9f9 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -129,6 +129,80 @@ | |||
129 | static int xgbe_poll(struct napi_struct *, int); | 129 | static int xgbe_poll(struct napi_struct *, int); |
130 | static void xgbe_set_rx_mode(struct net_device *); | 130 | static void xgbe_set_rx_mode(struct net_device *); |
131 | 131 | ||
132 | static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | ||
133 | { | ||
134 | struct xgbe_channel *channel_mem, *channel; | ||
135 | struct xgbe_ring *tx_ring, *rx_ring; | ||
136 | unsigned int count, i; | ||
137 | |||
138 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); | ||
139 | |||
140 | channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL); | ||
141 | if (!channel_mem) | ||
142 | goto err_channel; | ||
143 | |||
144 | tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring), | ||
145 | GFP_KERNEL); | ||
146 | if (!tx_ring) | ||
147 | goto err_tx_ring; | ||
148 | |||
149 | rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring), | ||
150 | GFP_KERNEL); | ||
151 | if (!rx_ring) | ||
152 | goto err_rx_ring; | ||
153 | |||
154 | for (i = 0, channel = channel_mem; i < count; i++, channel++) { | ||
155 | snprintf(channel->name, sizeof(channel->name), "channel-%d", i); | ||
156 | channel->pdata = pdata; | ||
157 | channel->queue_index = i; | ||
158 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + | ||
159 | (DMA_CH_INC * i); | ||
160 | |||
161 | if (i < pdata->tx_ring_count) { | ||
162 | spin_lock_init(&tx_ring->lock); | ||
163 | channel->tx_ring = tx_ring++; | ||
164 | } | ||
165 | |||
166 | if (i < pdata->rx_ring_count) { | ||
167 | spin_lock_init(&rx_ring->lock); | ||
168 | channel->rx_ring = rx_ring++; | ||
169 | } | ||
170 | |||
171 | DBGPR(" %s - queue_index=%u, dma_regs=%p, tx=%p, rx=%p\n", | ||
172 | channel->name, channel->queue_index, channel->dma_regs, | ||
173 | channel->tx_ring, channel->rx_ring); | ||
174 | } | ||
175 | |||
176 | pdata->channel = channel_mem; | ||
177 | pdata->channel_count = count; | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | err_rx_ring: | ||
182 | kfree(tx_ring); | ||
183 | |||
184 | err_tx_ring: | ||
185 | kfree(channel_mem); | ||
186 | |||
187 | err_channel: | ||
188 | netdev_err(pdata->netdev, "channel allocation failed\n"); | ||
189 | |||
190 | return -ENOMEM; | ||
191 | } | ||
192 | |||
193 | static void xgbe_free_channels(struct xgbe_prv_data *pdata) | ||
194 | { | ||
195 | if (!pdata->channel) | ||
196 | return; | ||
197 | |||
198 | kfree(pdata->channel->rx_ring); | ||
199 | kfree(pdata->channel->tx_ring); | ||
200 | kfree(pdata->channel); | ||
201 | |||
202 | pdata->channel = NULL; | ||
203 | pdata->channel_count = 0; | ||
204 | } | ||
205 | |||
132 | static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) | 206 | static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) |
133 | { | 207 | { |
134 | return (ring->rdesc_count - (ring->cur - ring->dirty)); | 208 | return (ring->rdesc_count - (ring->cur - ring->dirty)); |
@@ -1119,10 +1193,15 @@ static int xgbe_open(struct net_device *netdev) | |||
1119 | goto err_ptpclk; | 1193 | goto err_ptpclk; |
1120 | pdata->rx_buf_size = ret; | 1194 | pdata->rx_buf_size = ret; |
1121 | 1195 | ||
1196 | /* Allocate the channel and ring structures */ | ||
1197 | ret = xgbe_alloc_channels(pdata); | ||
1198 | if (ret) | ||
1199 | goto err_ptpclk; | ||
1200 | |||
1122 | /* Allocate the ring descriptors and buffers */ | 1201 | /* Allocate the ring descriptors and buffers */ |
1123 | ret = desc_if->alloc_ring_resources(pdata); | 1202 | ret = desc_if->alloc_ring_resources(pdata); |
1124 | if (ret) | 1203 | if (ret) |
1125 | goto err_ptpclk; | 1204 | goto err_channels; |
1126 | 1205 | ||
1127 | /* Initialize the device restart and Tx timestamp work struct */ | 1206 | /* Initialize the device restart and Tx timestamp work struct */ |
1128 | INIT_WORK(&pdata->restart_work, xgbe_restart); | 1207 | INIT_WORK(&pdata->restart_work, xgbe_restart); |
@@ -1134,7 +1213,7 @@ static int xgbe_open(struct net_device *netdev) | |||
1134 | if (ret) { | 1213 | if (ret) { |
1135 | netdev_alert(netdev, "error requesting irq %d\n", | 1214 | netdev_alert(netdev, "error requesting irq %d\n", |
1136 | pdata->irq_number); | 1215 | pdata->irq_number); |
1137 | goto err_irq; | 1216 | goto err_rings; |
1138 | } | 1217 | } |
1139 | pdata->irq_number = netdev->irq; | 1218 | pdata->irq_number = netdev->irq; |
1140 | 1219 | ||
@@ -1152,9 +1231,12 @@ err_start: | |||
1152 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); | 1231 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); |
1153 | pdata->irq_number = 0; | 1232 | pdata->irq_number = 0; |
1154 | 1233 | ||
1155 | err_irq: | 1234 | err_rings: |
1156 | desc_if->free_ring_resources(pdata); | 1235 | desc_if->free_ring_resources(pdata); |
1157 | 1236 | ||
1237 | err_channels: | ||
1238 | xgbe_free_channels(pdata); | ||
1239 | |||
1158 | err_ptpclk: | 1240 | err_ptpclk: |
1159 | clk_disable_unprepare(pdata->ptpclk); | 1241 | clk_disable_unprepare(pdata->ptpclk); |
1160 | 1242 | ||
@@ -1181,9 +1263,12 @@ static int xgbe_close(struct net_device *netdev) | |||
1181 | /* Issue software reset to device */ | 1263 | /* Issue software reset to device */ |
1182 | hw_if->exit(pdata); | 1264 | hw_if->exit(pdata); |
1183 | 1265 | ||
1184 | /* Free all the ring data */ | 1266 | /* Free the ring descriptors and buffers */ |
1185 | desc_if->free_ring_resources(pdata); | 1267 | desc_if->free_ring_resources(pdata); |
1186 | 1268 | ||
1269 | /* Free the channel and ring structures */ | ||
1270 | xgbe_free_channels(pdata); | ||
1271 | |||
1187 | /* Release the interrupt */ | 1272 | /* Release the interrupt */ |
1188 | if (pdata->irq_number != 0) { | 1273 | if (pdata->irq_number != 0) { |
1189 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); | 1274 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 49508ec98b72..47022fb00b79 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | |||
@@ -452,9 +452,9 @@ static int xgbe_set_coalesce(struct net_device *netdev, | |||
452 | rx_usecs); | 452 | rx_usecs); |
453 | return -EINVAL; | 453 | return -EINVAL; |
454 | } | 454 | } |
455 | if (rx_frames > pdata->channel->rx_ring->rdesc_count) { | 455 | if (rx_frames > pdata->rx_desc_count) { |
456 | netdev_alert(netdev, "rx-frames is limited to %d frames\n", | 456 | netdev_alert(netdev, "rx-frames is limited to %d frames\n", |
457 | pdata->channel->rx_ring->rdesc_count); | 457 | pdata->rx_desc_count); |
458 | return -EINVAL; | 458 | return -EINVAL; |
459 | } | 459 | } |
460 | 460 | ||
@@ -462,9 +462,9 @@ static int xgbe_set_coalesce(struct net_device *netdev, | |||
462 | tx_frames = ec->tx_max_coalesced_frames; | 462 | tx_frames = ec->tx_max_coalesced_frames; |
463 | 463 | ||
464 | /* Check the bounds of values for Tx */ | 464 | /* Check the bounds of values for Tx */ |
465 | if (tx_frames > pdata->channel->tx_ring->rdesc_count) { | 465 | if (tx_frames > pdata->tx_desc_count) { |
466 | netdev_alert(netdev, "tx-frames is limited to %d frames\n", | 466 | netdev_alert(netdev, "tx-frames is limited to %d frames\n", |
467 | pdata->channel->tx_ring->rdesc_count); | 467 | pdata->tx_desc_count); |
468 | return -EINVAL; | 468 | return -EINVAL; |
469 | } | 469 | } |
470 | 470 | ||
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index f5a8fa03921a..e5077fd5b012 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c | |||
@@ -133,60 +133,6 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
133 | MODULE_VERSION(XGBE_DRV_VERSION); | 133 | MODULE_VERSION(XGBE_DRV_VERSION); |
134 | MODULE_DESCRIPTION(XGBE_DRV_DESC); | 134 | MODULE_DESCRIPTION(XGBE_DRV_DESC); |
135 | 135 | ||
136 | static struct xgbe_channel *xgbe_alloc_rings(struct xgbe_prv_data *pdata) | ||
137 | { | ||
138 | struct xgbe_channel *channel_mem, *channel; | ||
139 | struct xgbe_ring *tx_ring, *rx_ring; | ||
140 | unsigned int count, i; | ||
141 | |||
142 | DBGPR("-->xgbe_alloc_rings\n"); | ||
143 | |||
144 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); | ||
145 | |||
146 | channel_mem = devm_kcalloc(pdata->dev, count, | ||
147 | sizeof(struct xgbe_channel), GFP_KERNEL); | ||
148 | if (!channel_mem) | ||
149 | return NULL; | ||
150 | |||
151 | tx_ring = devm_kcalloc(pdata->dev, pdata->tx_ring_count, | ||
152 | sizeof(struct xgbe_ring), GFP_KERNEL); | ||
153 | if (!tx_ring) | ||
154 | return NULL; | ||
155 | |||
156 | rx_ring = devm_kcalloc(pdata->dev, pdata->rx_ring_count, | ||
157 | sizeof(struct xgbe_ring), GFP_KERNEL); | ||
158 | if (!rx_ring) | ||
159 | return NULL; | ||
160 | |||
161 | for (i = 0, channel = channel_mem; i < count; i++, channel++) { | ||
162 | snprintf(channel->name, sizeof(channel->name), "channel-%d", i); | ||
163 | channel->pdata = pdata; | ||
164 | channel->queue_index = i; | ||
165 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + | ||
166 | (DMA_CH_INC * i); | ||
167 | |||
168 | if (i < pdata->tx_ring_count) { | ||
169 | spin_lock_init(&tx_ring->lock); | ||
170 | channel->tx_ring = tx_ring++; | ||
171 | } | ||
172 | |||
173 | if (i < pdata->rx_ring_count) { | ||
174 | spin_lock_init(&rx_ring->lock); | ||
175 | channel->rx_ring = rx_ring++; | ||
176 | } | ||
177 | |||
178 | DBGPR(" %s - queue_index=%u, dma_regs=%p, tx=%p, rx=%p\n", | ||
179 | channel->name, channel->queue_index, channel->dma_regs, | ||
180 | channel->tx_ring, channel->rx_ring); | ||
181 | } | ||
182 | |||
183 | pdata->channel_count = count; | ||
184 | |||
185 | DBGPR("<--xgbe_alloc_rings\n"); | ||
186 | |||
187 | return channel_mem; | ||
188 | } | ||
189 | |||
190 | static void xgbe_default_config(struct xgbe_prv_data *pdata) | 136 | static void xgbe_default_config(struct xgbe_prv_data *pdata) |
191 | { | 137 | { |
192 | DBGPR("-->xgbe_default_config\n"); | 138 | DBGPR("-->xgbe_default_config\n"); |
@@ -383,14 +329,6 @@ static int xgbe_probe(struct platform_device *pdev) | |||
383 | goto err_io; | 329 | goto err_io; |
384 | } | 330 | } |
385 | 331 | ||
386 | /* Allocate the rings for the DMA channels */ | ||
387 | pdata->channel = xgbe_alloc_rings(pdata); | ||
388 | if (!pdata->channel) { | ||
389 | dev_err(dev, "ring allocation failed\n"); | ||
390 | ret = -ENOMEM; | ||
391 | goto err_io; | ||
392 | } | ||
393 | |||
394 | /* Prepare to regsiter with MDIO */ | 332 | /* Prepare to regsiter with MDIO */ |
395 | pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name); | 333 | pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name); |
396 | if (!pdata->mii_bus_id) { | 334 | if (!pdata->mii_bus_id) { |