aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cassini.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/cassini.c')
-rw-r--r--drivers/net/cassini.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 40ff6a90d0da..86909cfb14de 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -74,6 +74,7 @@
74#include <linux/slab.h> 74#include <linux/slab.h>
75#include <linux/delay.h> 75#include <linux/delay.h>
76#include <linux/init.h> 76#include <linux/init.h>
77#include <linux/vmalloc.h>
77#include <linux/ioport.h> 78#include <linux/ioport.h>
78#include <linux/pci.h> 79#include <linux/pci.h>
79#include <linux/mm.h> 80#include <linux/mm.h>
@@ -91,6 +92,7 @@
91#include <linux/ip.h> 92#include <linux/ip.h>
92#include <linux/tcp.h> 93#include <linux/tcp.h>
93#include <linux/mutex.h> 94#include <linux/mutex.h>
95#include <linux/firmware.h>
94 96
95#include <net/checksum.h> 97#include <net/checksum.h>
96 98
@@ -197,6 +199,7 @@ static int link_mode;
197MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); 199MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
198MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); 200MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
199MODULE_LICENSE("GPL"); 201MODULE_LICENSE("GPL");
202MODULE_FIRMWARE("sun/cassini.bin");
200module_param(cassini_debug, int, 0); 203module_param(cassini_debug, int, 0);
201MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); 204MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
202module_param(link_mode, int, 0); 205module_param(link_mode, int, 0);
@@ -812,9 +815,44 @@ static int cas_reset_mii_phy(struct cas *cp)
812 return (limit <= 0); 815 return (limit <= 0);
813} 816}
814 817
818static int cas_saturn_firmware_init(struct cas *cp)
819{
820 const struct firmware *fw;
821 const char fw_name[] = "sun/cassini.bin";
822 int err;
823
824 if (PHY_NS_DP83065 != cp->phy_id)
825 return 0;
826
827 err = request_firmware(&fw, fw_name, &cp->pdev->dev);
828 if (err) {
829 printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n",
830 fw_name);
831 return err;
832 }
833 if (fw->size < 2) {
834 printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n",
835 fw->size, fw_name);
836 err = -EINVAL;
837 goto out;
838 }
839 cp->fw_load_addr= fw->data[1] << 8 | fw->data[0];
840 cp->fw_size = fw->size - 2;
841 cp->fw_data = vmalloc(cp->fw_size);
842 if (!cp->fw_data) {
843 err = -ENOMEM;
844 printk(KERN_ERR "cassini: \"%s\" Failed %d\n", fw_name, err);
845 goto out;
846 }
847 memcpy(cp->fw_data, &fw->data[2], cp->fw_size);
848out:
849 release_firmware(fw);
850 return err;
851}
852
815static void cas_saturn_firmware_load(struct cas *cp) 853static void cas_saturn_firmware_load(struct cas *cp)
816{ 854{
817 cas_saturn_patch_t *patch = cas_saturn_patch; 855 int i;
818 856
819 cas_phy_powerdown(cp); 857 cas_phy_powerdown(cp);
820 858
@@ -833,11 +871,9 @@ static void cas_saturn_firmware_load(struct cas *cp)
833 871
834 /* download new firmware */ 872 /* download new firmware */
835 cas_phy_write(cp, DP83065_MII_MEM, 0x1); 873 cas_phy_write(cp, DP83065_MII_MEM, 0x1);
836 cas_phy_write(cp, DP83065_MII_REGE, patch->addr); 874 cas_phy_write(cp, DP83065_MII_REGE, cp->fw_load_addr);
837 while (patch->addr) { 875 for (i = 0; i < cp->fw_size; i++)
838 cas_phy_write(cp, DP83065_MII_REGD, patch->val); 876 cas_phy_write(cp, DP83065_MII_REGD, cp->fw_data[i]);
839 patch++;
840 }
841 877
842 /* enable firmware */ 878 /* enable firmware */
843 cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8); 879 cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
@@ -5108,6 +5144,9 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
5108 cas_reset(cp, 0); 5144 cas_reset(cp, 0);
5109 if (cas_check_invariants(cp)) 5145 if (cas_check_invariants(cp))
5110 goto err_out_iounmap; 5146 goto err_out_iounmap;
5147 if (cp->cas_flags & CAS_FLAG_SATURN)
5148 if (cas_saturn_firmware_init(cp))
5149 goto err_out_iounmap;
5111 5150
5112 cp->init_block = (struct cas_init_block *) 5151 cp->init_block = (struct cas_init_block *)
5113 pci_alloc_consistent(pdev, sizeof(struct cas_init_block), 5152 pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
@@ -5217,6 +5256,9 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
5217 cp = netdev_priv(dev); 5256 cp = netdev_priv(dev);
5218 unregister_netdev(dev); 5257 unregister_netdev(dev);
5219 5258
5259 if (cp->fw_data)
5260 vfree(cp->fw_data);
5261
5220 mutex_lock(&cp->pm_mutex); 5262 mutex_lock(&cp->pm_mutex);
5221 flush_scheduled_work(); 5263 flush_scheduled_work();
5222 if (cp->hw_running) 5264 if (cp->hw_running)