]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/sky2.c
sky2: fix oops on shutdown
[linux-2.6-omap-h63xx.git] / drivers / net / sky2.c
index a35f2f2784ae0792c7cd4617464c526fe94130b7..3764008270a223eb816839069d7fc05987b44f49 100644 (file)
@@ -124,10 +124,7 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
-#ifdef broken
-       /* This device causes data corruption problems that are not resolved */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
-#endif
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
@@ -1392,7 +1389,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        /* Check for TCP Segmentation Offload */
        mss = skb_shinfo(skb)->gso_size;
        if (mss != 0) {
-               mss += ((skb->h.th->doff - 5) * 4);     /* TCP options */
+               mss += tcp_optlen(skb); /* TCP options */
                mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
                mss += ETH_HLEN;
 
@@ -1971,7 +1968,7 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,
                skb_reserve(skb, 2);
                pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
                                            length, PCI_DMA_FROMDEVICE);
-               memcpy(skb->data, re->skb->data, length);
+               skb_copy_from_linear_data(re->skb, skb->data, length);
                skb->ip_summed = re->skb->ip_summed;
                skb->csum = re->skb->csum;
                pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
@@ -3581,10 +3578,21 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out;
        }
 
+       /* Some Gigabyte motherboards have 88e8056 but cause problems
+        * There is some unresolved hardware related problem that causes
+        * descriptor errors and receive data corruption.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_MARVELL &&
+           pdev->device == 0x4364 && pdev->subsystem_vendor == 0x1458) {
+               dev_err(&pdev->dev,
+                       "88E8056 on Gigabyte motherboards not supported\n");
+               goto err_out_disable;
+       }
+
        err = pci_request_regions(pdev, DRV_NAME);
        if (err) {
                dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-               goto err_out;
+               goto err_out_disable;
        }
 
        pci_set_master(pdev);
@@ -3721,8 +3729,10 @@ err_out_free_hw:
        kfree(hw);
 err_out_free_regions:
        pci_release_regions(pdev);
+err_out_disable:
        pci_disable_device(pdev);
 err_out:
+       pci_set_drvdata(pdev, NULL);
        return err;
 }
 
@@ -3775,6 +3785,9 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
        struct sky2_hw *hw = pci_get_drvdata(pdev);
        int i, wol = 0;
 
+       if (!hw)
+               return 0;
+
        del_timer_sync(&hw->idle_timer);
        netif_poll_disable(hw->dev[0]);
 
@@ -3806,6 +3819,9 @@ static int sky2_resume(struct pci_dev *pdev)
        struct sky2_hw *hw = pci_get_drvdata(pdev);
        int i, err;
 
+       if (!hw)
+               return 0;
+
        err = pci_set_power_state(pdev, PCI_D0);
        if (err)
                goto out;
@@ -3852,6 +3868,9 @@ static void sky2_shutdown(struct pci_dev *pdev)
        struct sky2_hw *hw = pci_get_drvdata(pdev);
        int i, wol = 0;
 
+       if (!hw)
+               return;
+
        del_timer_sync(&hw->idle_timer);
        netif_poll_disable(hw->dev[0]);