Skip to content

Commit 68fd991

Browse files
Alexander Duyckdavem330
authored andcommitted
igb: Fix tx/rx_ring_count parameters for igb on suspend/resume/ring resize
When suspending the device the ring structure is freed which causes it to loose track of the count. To resolve this we need to move the ring count outside of the ring structure and store it in the adapter struct. In addition to resolving the suspend/resume issue this patch also addresses issues seen in the event of memory allocation errors causing uneven ring sizes on multiple queues. Signed-off-by: Alexander Duyck <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b2d5653 commit 68fd991

File tree

3 files changed

+59
-57
lines changed

3 files changed

+59
-57
lines changed

drivers/net/igb/igb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ struct igb_adapter {
294294
unsigned int lro_flushed;
295295
unsigned int lro_no_desc;
296296
#endif
297+
unsigned int tx_ring_count;
298+
unsigned int rx_ring_count;
297299
};
298300

299301
#define IGB_FLAG_HAS_MSI (1 << 0)
@@ -325,6 +327,8 @@ extern void igb_reset(struct igb_adapter *);
325327
extern int igb_set_spd_dplx(struct igb_adapter *, u16);
326328
extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *);
327329
extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *);
330+
extern void igb_free_tx_resources(struct igb_ring *);
331+
extern void igb_free_rx_resources(struct igb_ring *);
328332
extern void igb_update_stats(struct igb_adapter *);
329333
extern void igb_set_ethtool_ops(struct net_device *);
330334

drivers/net/igb/igb_ethtool.c

Lines changed: 49 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -714,15 +714,13 @@ static void igb_get_ringparam(struct net_device *netdev,
714714
struct ethtool_ringparam *ring)
715715
{
716716
struct igb_adapter *adapter = netdev_priv(netdev);
717-
struct igb_ring *tx_ring = adapter->tx_ring;
718-
struct igb_ring *rx_ring = adapter->rx_ring;
719717

720718
ring->rx_max_pending = IGB_MAX_RXD;
721719
ring->tx_max_pending = IGB_MAX_TXD;
722720
ring->rx_mini_max_pending = 0;
723721
ring->rx_jumbo_max_pending = 0;
724-
ring->rx_pending = rx_ring->count;
725-
ring->tx_pending = tx_ring->count;
722+
ring->rx_pending = adapter->rx_ring_count;
723+
ring->tx_pending = adapter->tx_ring_count;
726724
ring->rx_mini_pending = 0;
727725
ring->rx_jumbo_pending = 0;
728726
}
@@ -731,12 +729,9 @@ static int igb_set_ringparam(struct net_device *netdev,
731729
struct ethtool_ringparam *ring)
732730
{
733731
struct igb_adapter *adapter = netdev_priv(netdev);
734-
struct igb_buffer *old_buf;
735-
struct igb_buffer *old_rx_buf;
736-
void *old_desc;
732+
struct igb_ring *temp_ring;
737733
int i, err;
738-
u32 new_rx_count, new_tx_count, old_size;
739-
dma_addr_t old_dma;
734+
u32 new_rx_count, new_tx_count;
740735

741736
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
742737
return -EINVAL;
@@ -749,12 +744,19 @@ static int igb_set_ringparam(struct net_device *netdev,
749744
new_tx_count = min(new_tx_count, (u32)IGB_MAX_TXD);
750745
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
751746

752-
if ((new_tx_count == adapter->tx_ring->count) &&
753-
(new_rx_count == adapter->rx_ring->count)) {
747+
if ((new_tx_count == adapter->tx_ring_count) &&
748+
(new_rx_count == adapter->rx_ring_count)) {
754749
/* nothing to do */
755750
return 0;
756751
}
757752

753+
if (adapter->num_tx_queues > adapter->num_rx_queues)
754+
temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
755+
else
756+
temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
757+
if (!temp_ring)
758+
return -ENOMEM;
759+
758760
while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
759761
msleep(1);
760762

@@ -766,62 +768,55 @@ static int igb_set_ringparam(struct net_device *netdev,
766768
* because the ISRs in MSI-X mode get passed pointers
767769
* to the tx and rx ring structs.
768770
*/
769-
if (new_tx_count != adapter->tx_ring->count) {
771+
if (new_tx_count != adapter->tx_ring_count) {
772+
memcpy(temp_ring, adapter->tx_ring,
773+
adapter->num_tx_queues * sizeof(struct igb_ring));
774+
770775
for (i = 0; i < adapter->num_tx_queues; i++) {
771-
/* Save existing descriptor ring */
772-
old_buf = adapter->tx_ring[i].buffer_info;
773-
old_desc = adapter->tx_ring[i].desc;
774-
old_size = adapter->tx_ring[i].size;
775-
old_dma = adapter->tx_ring[i].dma;
776-
/* Try to allocate a new one */
777-
adapter->tx_ring[i].buffer_info = NULL;
778-
adapter->tx_ring[i].desc = NULL;
779-
adapter->tx_ring[i].count = new_tx_count;
780-
err = igb_setup_tx_resources(adapter,
781-
&adapter->tx_ring[i]);
776+
temp_ring[i].count = new_tx_count;
777+
err = igb_setup_tx_resources(adapter, &temp_ring[i]);
782778
if (err) {
783-
/* Restore the old one so at least
784-
the adapter still works, even if
785-
we failed the request */
786-
adapter->tx_ring[i].buffer_info = old_buf;
787-
adapter->tx_ring[i].desc = old_desc;
788-
adapter->tx_ring[i].size = old_size;
789-
adapter->tx_ring[i].dma = old_dma;
779+
while (i) {
780+
i--;
781+
igb_free_tx_resources(&temp_ring[i]);
782+
}
790783
goto err_setup;
791784
}
792-
/* Free the old buffer manually */
793-
vfree(old_buf);
794-
pci_free_consistent(adapter->pdev, old_size,
795-
old_desc, old_dma);
796785
}
786+
787+
for (i = 0; i < adapter->num_tx_queues; i++)
788+
igb_free_tx_resources(&adapter->tx_ring[i]);
789+
790+
memcpy(adapter->tx_ring, temp_ring,
791+
adapter->num_tx_queues * sizeof(struct igb_ring));
792+
793+
adapter->tx_ring_count = new_tx_count;
797794
}
798795

799796
if (new_rx_count != adapter->rx_ring->count) {
800-
for (i = 0; i < adapter->num_rx_queues; i++) {
797+
memcpy(temp_ring, adapter->rx_ring,
798+
adapter->num_rx_queues * sizeof(struct igb_ring));
801799

802-
old_rx_buf = adapter->rx_ring[i].buffer_info;
803-
old_desc = adapter->rx_ring[i].desc;
804-
old_size = adapter->rx_ring[i].size;
805-
old_dma = adapter->rx_ring[i].dma;
806-
807-
adapter->rx_ring[i].buffer_info = NULL;
808-
adapter->rx_ring[i].desc = NULL;
809-
adapter->rx_ring[i].dma = 0;
810-
adapter->rx_ring[i].count = new_rx_count;
811-
err = igb_setup_rx_resources(adapter,
812-
&adapter->rx_ring[i]);
800+
for (i = 0; i < adapter->num_rx_queues; i++) {
801+
temp_ring[i].count = new_rx_count;
802+
err = igb_setup_rx_resources(adapter, &temp_ring[i]);
813803
if (err) {
814-
adapter->rx_ring[i].buffer_info = old_rx_buf;
815-
adapter->rx_ring[i].desc = old_desc;
816-
adapter->rx_ring[i].size = old_size;
817-
adapter->rx_ring[i].dma = old_dma;
804+
while (i) {
805+
i--;
806+
igb_free_rx_resources(&temp_ring[i]);
807+
}
818808
goto err_setup;
819809
}
820810

821-
vfree(old_rx_buf);
822-
pci_free_consistent(adapter->pdev, old_size, old_desc,
823-
old_dma);
824811
}
812+
813+
for (i = 0; i < adapter->num_rx_queues; i++)
814+
igb_free_rx_resources(&adapter->rx_ring[i]);
815+
816+
memcpy(adapter->rx_ring, temp_ring,
817+
adapter->num_rx_queues * sizeof(struct igb_ring));
818+
819+
adapter->rx_ring_count = new_rx_count;
825820
}
826821

827822
err = 0;
@@ -830,6 +825,7 @@ static int igb_set_ringparam(struct net_device *netdev,
830825
igb_up(adapter);
831826

832827
clear_bit(__IGB_RESETTING, &adapter->state);
828+
vfree(temp_ring);
833829
return err;
834830
}
835831

drivers/net/igb/igb_main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ static int igb_setup_all_tx_resources(struct igb_adapter *);
7676
static int igb_setup_all_rx_resources(struct igb_adapter *);
7777
static void igb_free_all_tx_resources(struct igb_adapter *);
7878
static void igb_free_all_rx_resources(struct igb_adapter *);
79-
static void igb_free_tx_resources(struct igb_ring *);
80-
static void igb_free_rx_resources(struct igb_ring *);
8179
void igb_update_stats(struct igb_adapter *);
8280
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
8381
static void __devexit igb_remove(struct pci_dev *pdev);
@@ -259,11 +257,13 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
259257

260258
for (i = 0; i < adapter->num_tx_queues; i++) {
261259
struct igb_ring *ring = &(adapter->tx_ring[i]);
260+
ring->count = adapter->tx_ring_count;
262261
ring->adapter = adapter;
263262
ring->queue_index = i;
264263
}
265264
for (i = 0; i < adapter->num_rx_queues; i++) {
266265
struct igb_ring *ring = &(adapter->rx_ring[i]);
266+
ring->count = adapter->rx_ring_count;
267267
ring->adapter = adapter;
268268
ring->queue_index = i;
269269
ring->itr_register = E1000_ITR;
@@ -1400,6 +1400,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
14001400

14011401
pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);
14021402

1403+
adapter->tx_ring_count = IGB_DEFAULT_TXD;
1404+
adapter->rx_ring_count = IGB_DEFAULT_RXD;
14031405
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
14041406
adapter->rx_ps_hdr_size = 0; /* disable packet split */
14051407
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
@@ -1988,7 +1990,7 @@ static void igb_configure_rx(struct igb_adapter *adapter)
19881990
*
19891991
* Free all transmit software resources
19901992
**/
1991-
static void igb_free_tx_resources(struct igb_ring *tx_ring)
1993+
void igb_free_tx_resources(struct igb_ring *tx_ring)
19921994
{
19931995
struct pci_dev *pdev = tx_ring->adapter->pdev;
19941996

@@ -2088,7 +2090,7 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
20882090
*
20892091
* Free all receive software resources
20902092
**/
2091-
static void igb_free_rx_resources(struct igb_ring *rx_ring)
2093+
void igb_free_rx_resources(struct igb_ring *rx_ring)
20922094
{
20932095
struct pci_dev *pdev = rx_ring->adapter->pdev;
20942096

0 commit comments

Comments
 (0)