From 89d71a66c40d629e3b1285def543ab1425558cd5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 13 Oct 2009 05:34:20 +0000 Subject: net: Use netdev_alloc_skb_ip_align() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/e100.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/e100.c') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 679965c2bb8..ff83efd47b0 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1839,11 +1839,10 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) { - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) + if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) return -ENOMEM; - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); + /* Init, and map the RFD. */ skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); -- cgit v1.2.3-70-g09d2 From 7e15b0c9991dfe0bf05a2f8fab9154bb7827622e Mon Sep 17 00:00:00 2001 From: David Graham Date: Wed, 28 Oct 2009 04:13:57 -0700 Subject: e100: Fix to allow systems with FW based cards to resume from STD Devices with loadable firmware must have their firmware reloaded after the system resumes from sleep, but the request_firmare() API is not available at this point in the resume flow because tasks are not yet running, and the system will hang if it is called. Work around this issue by only calling request_firmware() for a device's first firmware load, and cache a copy of the pointer to the firmware blob for that device, so that we may reload firmware images even during resume. Signed-off-by: David Graham Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e100.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/net/e100.c') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index ff83efd47b0..f428c5f72f1 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -621,6 +621,7 @@ struct nic { u16 eeprom_wc; __le16 eeprom[256]; spinlock_t mdio_lock; + const struct firmware *fw; }; static inline void e100_write_flush(struct nic *nic) @@ -1222,9 +1223,9 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) static const struct firmware *e100_request_firmware(struct nic *nic) { const char *fw_name; - const struct firmware *fw; + const struct firmware *fw = nic->fw; u8 timer, bundle, min_size; - int err; + int err = 0; /* do not load u-code for ICH devices */ if (nic->flags & ich) @@ -1240,12 +1241,20 @@ static const struct firmware *e100_request_firmware(struct nic *nic) else /* No ucode on other devices */ return NULL; - err = request_firmware(&fw, fw_name, &nic->pdev->dev); + /* If the firmware has not previously been loaded, request a pointer + * to it. If it was previously loaded, we are reinitializing the + * adapter, possibly in a resume from hibernate, in which case + * request_firmware() cannot be used. + */ + if (!fw) + err = request_firmware(&fw, fw_name, &nic->pdev->dev); + if (err) { DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", fw_name, err); return ERR_PTR(err); } + /* Firmware should be precisely UCODE_SIZE (words) plus three bytes indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ if (fw->size != UCODE_SIZE * 4 + 3) { @@ -1268,7 +1277,10 @@ static const struct firmware *e100_request_firmware(struct nic *nic) release_firmware(fw); return ERR_PTR(-EINVAL); } - /* OK, firmware is validated and ready to use... */ + + /* OK, firmware is validated and ready to use. Save a pointer + * to it in the nic */ + nic->fw = fw; return fw; } -- cgit v1.2.3-70-g09d2 From 98468efddb101f8a29af974101c17ba513b07be1 Mon Sep 17 00:00:00 2001 From: Roger Oksanen Date: Sun, 29 Nov 2009 17:17:29 -0800 Subject: e100: Use pci pool to work around GFP_ATOMIC order 5 memory allocation failure pci_alloc_consistent uses GFP_ATOMIC allocation that may fail on some systems with limited memory (Bug #14265). pci_pool_alloc allows waiting with GFP_KERNEL. Tested-by: Karol Lewandowski Signed-off-by: Roger Oksanen Signed-off-by: David S. Miller --- drivers/net/e100.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net/e100.c') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3c29a20b751..d269a68ce35 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -157,6 +157,7 @@ #include #include #include +#include #include #include #include @@ -602,6 +603,7 @@ struct nic { struct mem *mem; dma_addr_t dma_addr; + struct pci_pool *cbs_pool; dma_addr_t cbs_dma_addr; u8 adaptive_ifs; u8 tx_threshold; @@ -1793,9 +1795,7 @@ static void e100_clean_cbs(struct nic *nic) nic->cb_to_clean = nic->cb_to_clean->next; nic->cbs_avail++; } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); + pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); nic->cbs = NULL; nic->cbs_avail = 0; } @@ -1813,8 +1813,8 @@ static int e100_alloc_cbs(struct nic *nic) nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; nic->cbs_avail = 0; - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); + nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, + &nic->cbs_dma_addr); if (!nic->cbs) return -ENOMEM; @@ -2841,7 +2841,11 @@ static int __devinit e100_probe(struct pci_dev *pdev, DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); goto err_out_free; } - + nic->cbs_pool = pci_pool_create(netdev->name, + nic->pdev, + nic->params.cbs.count * sizeof(struct cb), + sizeof(u32), + 0); DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), pdev->irq, netdev->dev_addr); @@ -2871,6 +2875,7 @@ static void __devexit e100_remove(struct pci_dev *pdev) unregister_netdev(netdev); e100_free(nic); pci_iounmap(pdev, nic->csr); + pci_pool_destroy(nic->cbs_pool); free_netdev(netdev); pci_release_regions(pdev); pci_disable_device(pdev); -- cgit v1.2.3-70-g09d2