aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e100.c
diff options
context:
space:
mode:
authorJaswinder Singh Rajput <jaswinderrajput@gmail.com>2009-01-07 15:59:17 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-07 15:59:17 -0500
commit9ac32e1bc0518b01b47dd34a733dce8634a38ed3 (patch)
tree4316ea3a959cab393289c67364ee63f06e34543c /drivers/net/e100.c
parent92dc8cc317844e5681f5d8990896720ed2b21cc8 (diff)
firmware: convert e100 driver to request_firmware()
Thanks to David Woodhouse for help. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e100.c')
-rw-r--r--drivers/net/e100.c299
1 files changed, 97 insertions, 202 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 134b2d60b479..86bb876fb123 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -161,6 +161,7 @@
161#include <linux/skbuff.h> 161#include <linux/skbuff.h>
162#include <linux/ethtool.h> 162#include <linux/ethtool.h>
163#include <linux/string.h> 163#include <linux/string.h>
164#include <linux/firmware.h>
164#include <asm/unaligned.h> 165#include <asm/unaligned.h>
165 166
166 167
@@ -174,10 +175,17 @@
174#define E100_WATCHDOG_PERIOD (2 * HZ) 175#define E100_WATCHDOG_PERIOD (2 * HZ)
175#define E100_NAPI_WEIGHT 16 176#define E100_NAPI_WEIGHT 16
176 177
178#define FIRMWARE_D101M "e100/d101m_ucode.bin"
179#define FIRMWARE_D101S "e100/d101s_ucode.bin"
180#define FIRMWARE_D102E "e100/d102e_ucode.bin"
181
177MODULE_DESCRIPTION(DRV_DESCRIPTION); 182MODULE_DESCRIPTION(DRV_DESCRIPTION);
178MODULE_AUTHOR(DRV_COPYRIGHT); 183MODULE_AUTHOR(DRV_COPYRIGHT);
179MODULE_LICENSE("GPL"); 184MODULE_LICENSE("GPL");
180MODULE_VERSION(DRV_VERSION); 185MODULE_VERSION(DRV_VERSION);
186MODULE_FIRMWARE(FIRMWARE_D101M);
187MODULE_FIRMWARE(FIRMWARE_D101S);
188MODULE_FIRMWARE(FIRMWARE_D102E);
181 189
182static int debug = 3; 190static int debug = 3;
183static int eeprom_bad_csum_allow = 0; 191static int eeprom_bad_csum_allow = 0;
@@ -1049,178 +1057,6 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
1049 c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); 1057 c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
1050} 1058}
1051 1059
1052/********************************************************/
1053/* Micro code for 8086:1229 Rev 8 */
1054/********************************************************/
1055
1056/* Parameter values for the D101M B-step */
1057#define D101M_CPUSAVER_TIMER_DWORD 78
1058#define D101M_CPUSAVER_BUNDLE_DWORD 65
1059#define D101M_CPUSAVER_MIN_SIZE_DWORD 126
1060
1061#define D101M_B_RCVBUNDLE_UCODE \
1062{\
10630x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
10640x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
10650x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
10660x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
10670x00380438, 0x00000000, 0x00140000, 0x00380555, \
10680x00308000, 0x00100662, 0x00100561, 0x000E0408, \
10690x00134861, 0x000C0002, 0x00103093, 0x00308000, \
10700x00100624, 0x00100561, 0x000E0408, 0x00100861, \
10710x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
10720x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
10730x00000000, 0x00000000, 0x00000000, 0x00000000, \
10740x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
10750x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
10760x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
10770x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
10780x00041000, 0x00010004, 0x00130826, 0x000C0006, \
10790x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
10800x00000000, 0x00000000, 0x00000000, 0x00000000, \
10810x00000000, 0x00000000, 0x00000000, 0x00000000, \
10820x00080600, 0x00101B10, 0x00050004, 0x00100826, \
10830x00101210, 0x00380C34, 0x00000000, 0x00000000, \
10840x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
10850x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
10860x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
10870x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
10880x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
10890x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
10900x00130826, 0x000C0001, 0x00220559, 0x00101313, \
10910x00380559, 0x00000000, 0x00000000, 0x00000000, \
10920x00000000, 0x00000000, 0x00000000, 0x00000000, \
10930x00000000, 0x00130831, 0x0010090B, 0x00124813, \
10940x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
10950x003806A8, 0x00000000, 0x00000000, 0x00000000, \
1096}
1097
1098/********************************************************/
1099/* Micro code for 8086:1229 Rev 9 */
1100/********************************************************/
1101
1102/* Parameter values for the D101S */
1103#define D101S_CPUSAVER_TIMER_DWORD 78
1104#define D101S_CPUSAVER_BUNDLE_DWORD 67
1105#define D101S_CPUSAVER_MIN_SIZE_DWORD 128
1106
1107#define D101S_RCVBUNDLE_UCODE \
1108{\
11090x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
11100x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
11110x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
11120x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
11130x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
11140x00308000, 0x00100610, 0x00100561, 0x000E0408, \
11150x00134861, 0x000C0002, 0x00103093, 0x00308000, \
11160x00100624, 0x00100561, 0x000E0408, 0x00100861, \
11170x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
11180x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
11190x00000000, 0x00000000, 0x00000000, 0x00000000, \
11200x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
11210x003A047E, 0x00044010, 0x00380819, 0x00000000, \
11220x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
11230x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
11240x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
11250x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
11260x00101313, 0x00380700, 0x00000000, 0x00000000, \
11270x00000000, 0x00000000, 0x00000000, 0x00000000, \
11280x00080600, 0x00101B10, 0x00050004, 0x00100826, \
11290x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
11300x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
11310x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
11320x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
11330x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
11340x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
11350x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
11360x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
11370x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
11380x00000000, 0x00000000, 0x00000000, 0x00000000, \
11390x00000000, 0x00000000, 0x00000000, 0x00130831, \
11400x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
11410x00041000, 0x00010004, 0x00380700 \
1142}
1143
1144/********************************************************/
1145/* Micro code for the 8086:1229 Rev F/10 */
1146/********************************************************/
1147
1148/* Parameter values for the D102 E-step */
1149#define D102_E_CPUSAVER_TIMER_DWORD 42
1150#define D102_E_CPUSAVER_BUNDLE_DWORD 54
1151#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46
1152
1153#define D102_E_RCVBUNDLE_UCODE \
1154{\
11550x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
11560x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
11570x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
11580x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
11590x00000000, 0x00000000, 0x00000000, 0x00000000, \
11600x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
11610x00000000, 0x00000000, 0x00000000, 0x00000000, \
11620x00000000, 0x00000000, 0x00000000, 0x00000000, \
11630x00000000, 0x00000000, 0x00000000, 0x00000000, \
11640x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
11650x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
11660x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
11670x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
11680x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
11690x00000000, 0x00000000, 0x00000000, 0x00000000, \
11700x00000000, 0x00000000, 0x00000000, 0x00000000, \
11710x00000000, 0x00000000, 0x00000000, 0x00000000, \
11720x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
11730x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
11740x00000000, 0x00000000, 0x00000000, 0x00000000, \
11750x00000000, 0x00000000, 0x00000000, 0x00000000, \
11760x00000000, 0x00000000, 0x00000000, 0x00000000, \
11770x00000000, 0x00000000, 0x00000000, 0x00000000, \
11780x00000000, 0x00000000, 0x00000000, 0x00000000, \
11790x00000000, 0x00000000, 0x00000000, 0x00000000, \
11800x00000000, 0x00000000, 0x00000000, 0x00000000, \
11810x00000000, 0x00000000, 0x00000000, 0x00000000, \
11820x00000000, 0x00000000, 0x00000000, 0x00000000, \
11830x00000000, 0x00000000, 0x00000000, 0x00000000, \
11840x00000000, 0x00000000, 0x00000000, 0x00000000, \
11850x00000000, 0x00000000, 0x00000000, 0x00000000, \
11860x00000000, 0x00000000, 0x00000000, 0x00000000, \
11870x00000000, 0x00000000, 0x00000000, 0x00000000, \
1188}
1189
1190static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
1191{
1192/* *INDENT-OFF* */
1193 static struct {
1194 u32 ucode[UCODE_SIZE + 1];
1195 u8 mac;
1196 u8 timer_dword;
1197 u8 bundle_dword;
1198 u8 min_size_dword;
1199 } ucode_opts[] = {
1200 { D101M_B_RCVBUNDLE_UCODE,
1201 mac_82559_D101M,
1202 D101M_CPUSAVER_TIMER_DWORD,
1203 D101M_CPUSAVER_BUNDLE_DWORD,
1204 D101M_CPUSAVER_MIN_SIZE_DWORD },
1205 { D101S_RCVBUNDLE_UCODE,
1206 mac_82559_D101S,
1207 D101S_CPUSAVER_TIMER_DWORD,
1208 D101S_CPUSAVER_BUNDLE_DWORD,
1209 D101S_CPUSAVER_MIN_SIZE_DWORD },
1210 { D102_E_RCVBUNDLE_UCODE,
1211 mac_82551_F,
1212 D102_E_CPUSAVER_TIMER_DWORD,
1213 D102_E_CPUSAVER_BUNDLE_DWORD,
1214 D102_E_CPUSAVER_MIN_SIZE_DWORD },
1215 { D102_E_RCVBUNDLE_UCODE,
1216 mac_82551_10,
1217 D102_E_CPUSAVER_TIMER_DWORD,
1218 D102_E_CPUSAVER_BUNDLE_DWORD,
1219 D102_E_CPUSAVER_MIN_SIZE_DWORD },
1220 { {0}, 0, 0, 0, 0}
1221 }, *opts;
1222/* *INDENT-ON* */
1223
1224/************************************************************************* 1060/*************************************************************************
1225* CPUSaver parameters 1061* CPUSaver parameters
1226* 1062*
@@ -1280,42 +1116,101 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
1280#define BUNDLEMAX (u16)6 1116#define BUNDLEMAX (u16)6
1281#define INTDELAY (u16)1536 /* 0x600 */ 1117#define INTDELAY (u16)1536 /* 0x600 */
1282 1118
1119/* Initialize firmware */
1120static const struct firmware *e100_request_firmware(struct nic *nic)
1121{
1122 const char *fw_name;
1123 const struct firmware *fw;
1124 u8 timer, bundle, min_size;
1125 int err;
1126
1283 /* do not load u-code for ICH devices */ 1127 /* do not load u-code for ICH devices */
1284 if (nic->flags & ich) 1128 if (nic->flags & ich)
1285 goto noloaducode; 1129 return NULL;
1286 1130
1287 /* Search for ucode match against h/w revision */ 1131 /* Search for ucode match against h/w revision */
1288 for (opts = ucode_opts; opts->mac; opts++) { 1132 if (nic->mac == mac_82559_D101M)
1289 int i; 1133 fw_name = FIRMWARE_D101M;
1290 u32 *ucode = opts->ucode; 1134 else if (nic->mac == mac_82559_D101S)
1291 if (nic->mac != opts->mac) 1135 fw_name = FIRMWARE_D101S;
1292 continue; 1136 else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
1293 1137 fw_name = FIRMWARE_D102E;
1294 /* Insert user-tunable settings */ 1138 else /* No ucode on other devices */
1295 ucode[opts->timer_dword] &= 0xFFFF0000; 1139 return NULL;
1296 ucode[opts->timer_dword] |= INTDELAY; 1140
1297 ucode[opts->bundle_dword] &= 0xFFFF0000; 1141 err = request_firmware(&fw, fw_name, &nic->pdev->dev);
1298 ucode[opts->bundle_dword] |= BUNDLEMAX; 1142 if (err) {
1299 ucode[opts->min_size_dword] &= 0xFFFF0000; 1143 DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n",
1300 ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; 1144 fw_name, err);
1301 1145 return ERR_PTR(err);
1302 for (i = 0; i < UCODE_SIZE; i++) 1146 }
1303 cb->u.ucode[i] = cpu_to_le32(ucode[i]); 1147 /* Firmware should be precisely UCODE_SIZE (words) plus three bytes
1304 cb->command = cpu_to_le16(cb_ucode | cb_el); 1148 indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
1305 return; 1149 if (fw->size != UCODE_SIZE * 4 + 3) {
1306 } 1150 DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n",
1307 1151 fw_name, fw->size);
1308noloaducode: 1152 release_firmware(fw);
1309 cb->command = cpu_to_le16(cb_nop | cb_el); 1153 return ERR_PTR(-EINVAL);
1310} 1154 }
1311 1155
1312static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, 1156 /* Read timer, bundle and min_size from end of firmware blob */
1313 void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) 1157 timer = fw->data[UCODE_SIZE * 4];
1314{ 1158 bundle = fw->data[UCODE_SIZE * 4 + 1];
1159 min_size = fw->data[UCODE_SIZE * 4 + 2];
1160
1161 if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
1162 min_size >= UCODE_SIZE) {
1163 DPRINTK(PROBE, ERR,
1164 "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
1165 fw_name, timer, bundle, min_size);
1166 release_firmware(fw);
1167 return ERR_PTR(-EINVAL);
1168 }
1169 /* OK, firmware is validated and ready to use... */
1170 return fw;
1171}
1172
1173static void e100_setup_ucode(struct nic *nic, struct cb *cb,
1174 struct sk_buff *skb)
1175{
1176 const struct firmware *fw = (void *)skb;
1177 u8 timer, bundle, min_size;
1178
1179 /* It's not a real skb; we just abused the fact that e100_exec_cb
1180 will pass it through to here... */
1181 cb->skb = NULL;
1182
1183 /* firmware is stored as little endian already */
1184 memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);
1185
1186 /* Read timer, bundle and min_size from end of firmware blob */
1187 timer = fw->data[UCODE_SIZE * 4];
1188 bundle = fw->data[UCODE_SIZE * 4 + 1];
1189 min_size = fw->data[UCODE_SIZE * 4 + 2];
1190
1191 /* Insert user-tunable settings in cb->u.ucode */
1192 cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
1193 cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
1194 cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
1195 cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
1196 cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
1197 cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
1198
1199 cb->command = cpu_to_le16(cb_ucode | cb_el);
1200}
1201
1202static inline int e100_load_ucode_wait(struct nic *nic)
1203{
1204 const struct firmware *fw;
1315 int err = 0, counter = 50; 1205 int err = 0, counter = 50;
1316 struct cb *cb = nic->cb_to_clean; 1206 struct cb *cb = nic->cb_to_clean;
1317 1207
1318 if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) 1208 fw = e100_request_firmware(nic);
1209 /* If it's NULL, then no ucode is required */
1210 if (!fw || IS_ERR(fw))
1211 return PTR_ERR(fw);
1212
1213 if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
1319 DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); 1214 DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
1320 1215
1321 /* must restart cuc */ 1216 /* must restart cuc */
@@ -1435,7 +1330,7 @@ static int e100_hw_init(struct nic *nic)
1435 return err; 1330 return err;
1436 if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) 1331 if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
1437 return err; 1332 return err;
1438 if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) 1333 if ((err = e100_load_ucode_wait(nic)))
1439 return err; 1334 return err;
1440 if ((err = e100_exec_cb(nic, NULL, e100_configure))) 1335 if ((err = e100_exec_cb(nic, NULL, e100_configure)))
1441 return err; 1336 return err;