diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-12-01 19:36:16 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-02 00:24:49 -0500 |
commit | f1d3d38af75789f1b82969b83b69cab540609789 (patch) | |
tree | 47d31e8a55fb65cf33797197b92a332630cfc3ef /drivers/net/chelsio/cxgb2.c | |
parent | 415294ecbb32ddbd0a7a2b7bae0b60fedfa09cc4 (diff) |
[PATCH] chelsio: add support for other 10G boards
Add support for other versions of the 10G Chelsio boards.
This is basically a port of the vendor driver with the
TOE features removed.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/chelsio/cxgb2.c')
-rw-r--r-- | drivers/net/chelsio/cxgb2.c | 238 |
1 files changed, 226 insertions, 12 deletions
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 42ad9cfd670a..a8c873b0af54 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c | |||
@@ -53,7 +53,9 @@ | |||
53 | #include "gmac.h" | 53 | #include "gmac.h" |
54 | #include "cphy.h" | 54 | #include "cphy.h" |
55 | #include "sge.h" | 55 | #include "sge.h" |
56 | #include "tp.h" | ||
56 | #include "espi.h" | 57 | #include "espi.h" |
58 | #include "elmer0.h" | ||
57 | 59 | ||
58 | #include <linux/workqueue.h> | 60 | #include <linux/workqueue.h> |
59 | 61 | ||
@@ -73,10 +75,9 @@ static inline void cancel_mac_stats_update(struct adapter *ap) | |||
73 | #define MAX_RX_JUMBO_BUFFERS 16384 | 75 | #define MAX_RX_JUMBO_BUFFERS 16384 |
74 | #define MAX_TX_BUFFERS_HIGH 16384U | 76 | #define MAX_TX_BUFFERS_HIGH 16384U |
75 | #define MAX_TX_BUFFERS_LOW 1536U | 77 | #define MAX_TX_BUFFERS_LOW 1536U |
78 | #define MAX_TX_BUFFERS 1460U | ||
76 | #define MIN_FL_ENTRIES 32 | 79 | #define MIN_FL_ENTRIES 32 |
77 | 80 | ||
78 | #define PORT_MASK ((1 << MAX_NPORTS) - 1) | ||
79 | |||
80 | #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ | 81 | #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ |
81 | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ | 82 | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ |
82 | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) | 83 | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) |
@@ -94,8 +95,17 @@ MODULE_LICENSE("GPL"); | |||
94 | static int dflt_msg_enable = DFLT_MSG_ENABLE; | 95 | static int dflt_msg_enable = DFLT_MSG_ENABLE; |
95 | 96 | ||
96 | module_param(dflt_msg_enable, int, 0); | 97 | module_param(dflt_msg_enable, int, 0); |
97 | MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap"); | 98 | MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap"); |
99 | |||
100 | #define HCLOCK 0x0 | ||
101 | #define LCLOCK 0x1 | ||
102 | |||
103 | /* T1 cards powersave mode */ | ||
104 | static int t1_clock(struct adapter *adapter, int mode); | ||
105 | static int t1powersave = 1; /* HW default is powersave mode. */ | ||
98 | 106 | ||
107 | module_param(t1powersave, int, 0); | ||
108 | MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode"); | ||
99 | 109 | ||
100 | static const char pci_speed[][4] = { | 110 | static const char pci_speed[][4] = { |
101 | "33", "66", "100", "133" | 111 | "33", "66", "100", "133" |
@@ -135,7 +145,7 @@ static void link_report(struct port_info *p) | |||
135 | } | 145 | } |
136 | } | 146 | } |
137 | 147 | ||
138 | void t1_link_changed(struct adapter *adapter, int port_id, int link_stat, | 148 | void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat, |
139 | int speed, int duplex, int pause) | 149 | int speed, int duplex, int pause) |
140 | { | 150 | { |
141 | struct port_info *p = &adapter->port[port_id]; | 151 | struct port_info *p = &adapter->port[port_id]; |
@@ -147,6 +157,22 @@ void t1_link_changed(struct adapter *adapter, int port_id, int link_stat, | |||
147 | netif_carrier_off(p->dev); | 157 | netif_carrier_off(p->dev); |
148 | link_report(p); | 158 | link_report(p); |
149 | 159 | ||
160 | /* multi-ports: inform toe */ | ||
161 | if ((speed > 0) && (adapter->params.nports > 1)) { | ||
162 | unsigned int sched_speed = 10; | ||
163 | switch (speed) { | ||
164 | case SPEED_1000: | ||
165 | sched_speed = 1000; | ||
166 | break; | ||
167 | case SPEED_100: | ||
168 | sched_speed = 100; | ||
169 | break; | ||
170 | case SPEED_10: | ||
171 | sched_speed = 10; | ||
172 | break; | ||
173 | } | ||
174 | t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed); | ||
175 | } | ||
150 | } | 176 | } |
151 | } | 177 | } |
152 | 178 | ||
@@ -165,8 +191,10 @@ static void link_start(struct port_info *p) | |||
165 | static void enable_hw_csum(struct adapter *adapter) | 191 | static void enable_hw_csum(struct adapter *adapter) |
166 | { | 192 | { |
167 | if (adapter->flags & TSO_CAPABLE) | 193 | if (adapter->flags & TSO_CAPABLE) |
168 | t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */ | 194 | t1_tp_set_ip_checksum_offload(adapter->tp, 1); /* for TSO only */ |
169 | t1_tp_set_tcp_checksum_offload(adapter, 1); | 195 | if (adapter->flags & UDP_CSUM_CAPABLE) |
196 | t1_tp_set_udp_checksum_offload(adapter->tp, 1); | ||
197 | t1_tp_set_tcp_checksum_offload(adapter->tp, 1); | ||
170 | } | 198 | } |
171 | 199 | ||
172 | /* | 200 | /* |
@@ -468,6 +496,18 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, | |||
468 | *data++ = (u64)t->tx_reg_pkts; | 496 | *data++ = (u64)t->tx_reg_pkts; |
469 | *data++ = (u64)t->tx_lso_pkts; | 497 | *data++ = (u64)t->tx_lso_pkts; |
470 | *data++ = (u64)t->tx_do_cksum; | 498 | *data++ = (u64)t->tx_do_cksum; |
499 | |||
500 | if (adapter->espi) { | ||
501 | const struct espi_intr_counts *e; | ||
502 | |||
503 | e = t1_espi_get_intr_counts(adapter->espi); | ||
504 | *data++ = (u64) e->DIP2_parity_err; | ||
505 | *data++ = (u64) e->DIP4_err; | ||
506 | *data++ = (u64) e->rx_drops; | ||
507 | *data++ = (u64) e->tx_drops; | ||
508 | *data++ = (u64) e->rx_ovflw; | ||
509 | *data++ = (u64) e->parity_err; | ||
510 | } | ||
471 | } | 511 | } |
472 | 512 | ||
473 | static inline void reg_block_dump(struct adapter *ap, void *buf, | 513 | static inline void reg_block_dump(struct adapter *ap, void *buf, |
@@ -491,6 +531,15 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
491 | 531 | ||
492 | memset(buf, 0, T2_REGMAP_SIZE); | 532 | memset(buf, 0, T2_REGMAP_SIZE); |
493 | reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER); | 533 | reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER); |
534 | reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE); | ||
535 | reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR); | ||
536 | reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT); | ||
537 | reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE); | ||
538 | reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE); | ||
539 | reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT); | ||
540 | reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL); | ||
541 | reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE); | ||
542 | reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD); | ||
494 | } | 543 | } |
495 | 544 | ||
496 | static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 545 | static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
@@ -729,7 +778,9 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | |||
729 | 778 | ||
730 | static int get_eeprom_len(struct net_device *dev) | 779 | static int get_eeprom_len(struct net_device *dev) |
731 | { | 780 | { |
732 | return EEPROM_SIZE; | 781 | struct adapter *adapter = dev->priv; |
782 | |||
783 | return t1_is_asic(adapter) ? EEPROM_SIZE : 0; | ||
733 | } | 784 | } |
734 | 785 | ||
735 | #define EEPROM_MAGIC(ap) \ | 786 | #define EEPROM_MAGIC(ap) \ |
@@ -914,7 +965,7 @@ static void ext_intr_task(void *data) | |||
914 | { | 965 | { |
915 | struct adapter *adapter = data; | 966 | struct adapter *adapter = data; |
916 | 967 | ||
917 | elmer0_ext_intr_handler(adapter); | 968 | t1_elmer0_ext_intr_handler(adapter); |
918 | 969 | ||
919 | /* Now reenable external interrupts */ | 970 | /* Now reenable external interrupts */ |
920 | spin_lock_irq(&adapter->async_lock); | 971 | spin_lock_irq(&adapter->async_lock); |
@@ -1074,16 +1125,19 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
1074 | netdev->vlan_rx_register = vlan_rx_register; | 1125 | netdev->vlan_rx_register = vlan_rx_register; |
1075 | netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; | 1126 | netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; |
1076 | #endif | 1127 | #endif |
1077 | adapter->flags |= TSO_CAPABLE; | 1128 | |
1078 | netdev->features |= NETIF_F_TSO; | 1129 | /* T204: disable TSO */ |
1130 | if (!(is_T2(adapter)) || bi->port_number != 4) { | ||
1131 | adapter->flags |= TSO_CAPABLE; | ||
1132 | netdev->features |= NETIF_F_TSO; | ||
1133 | } | ||
1079 | } | 1134 | } |
1080 | 1135 | ||
1081 | netdev->open = cxgb_open; | 1136 | netdev->open = cxgb_open; |
1082 | netdev->stop = cxgb_close; | 1137 | netdev->stop = cxgb_close; |
1083 | netdev->hard_start_xmit = t1_start_xmit; | 1138 | netdev->hard_start_xmit = t1_start_xmit; |
1084 | netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ? | 1139 | netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ? |
1085 | sizeof(struct cpl_tx_pkt_lso) : | 1140 | sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt); |
1086 | sizeof(struct cpl_tx_pkt); | ||
1087 | netdev->get_stats = t1_get_stats; | 1141 | netdev->get_stats = t1_get_stats; |
1088 | netdev->set_multicast_list = t1_set_rxmode; | 1142 | netdev->set_multicast_list = t1_set_rxmode; |
1089 | netdev->do_ioctl = t1_ioctl; | 1143 | netdev->do_ioctl = t1_ioctl; |
@@ -1134,6 +1188,17 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
1134 | bi->desc, adapter->params.chip_revision, | 1188 | bi->desc, adapter->params.chip_revision, |
1135 | adapter->params.pci.is_pcix ? "PCIX" : "PCI", | 1189 | adapter->params.pci.is_pcix ? "PCIX" : "PCI", |
1136 | adapter->params.pci.speed, adapter->params.pci.width); | 1190 | adapter->params.pci.speed, adapter->params.pci.width); |
1191 | |||
1192 | /* | ||
1193 | * Set the T1B ASIC and memory clocks. | ||
1194 | */ | ||
1195 | if (t1powersave) | ||
1196 | adapter->t1powersave = LCLOCK; /* HW default is powersave mode. */ | ||
1197 | else | ||
1198 | adapter->t1powersave = HCLOCK; | ||
1199 | if (t1_is_T1B(adapter)) | ||
1200 | t1_clock(adapter, t1powersave); | ||
1201 | |||
1137 | return 0; | 1202 | return 0; |
1138 | 1203 | ||
1139 | out_release_adapter_res: | 1204 | out_release_adapter_res: |
@@ -1153,6 +1218,155 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
1153 | return err; | 1218 | return err; |
1154 | } | 1219 | } |
1155 | 1220 | ||
1221 | static void bit_bang(struct adapter *adapter, int bitdata, int nbits) | ||
1222 | { | ||
1223 | int data; | ||
1224 | int i; | ||
1225 | u32 val; | ||
1226 | |||
1227 | enum { | ||
1228 | S_CLOCK = 1 << 3, | ||
1229 | S_DATA = 1 << 4 | ||
1230 | }; | ||
1231 | |||
1232 | for (i = (nbits - 1); i > -1; i--) { | ||
1233 | |||
1234 | udelay(50); | ||
1235 | |||
1236 | data = ((bitdata >> i) & 0x1); | ||
1237 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1238 | |||
1239 | if (data) | ||
1240 | val |= S_DATA; | ||
1241 | else | ||
1242 | val &= ~S_DATA; | ||
1243 | |||
1244 | udelay(50); | ||
1245 | |||
1246 | /* Set SCLOCK low */ | ||
1247 | val &= ~S_CLOCK; | ||
1248 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1249 | |||
1250 | udelay(50); | ||
1251 | |||
1252 | /* Write SCLOCK high */ | ||
1253 | val |= S_CLOCK; | ||
1254 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1255 | |||
1256 | } | ||
1257 | } | ||
1258 | |||
1259 | static int t1_clock(struct adapter *adapter, int mode) | ||
1260 | { | ||
1261 | u32 val; | ||
1262 | int M_CORE_VAL; | ||
1263 | int M_MEM_VAL; | ||
1264 | |||
1265 | enum { | ||
1266 | M_CORE_BITS = 9, | ||
1267 | T_CORE_VAL = 0, | ||
1268 | T_CORE_BITS = 2, | ||
1269 | N_CORE_VAL = 0, | ||
1270 | N_CORE_BITS = 2, | ||
1271 | M_MEM_BITS = 9, | ||
1272 | T_MEM_VAL = 0, | ||
1273 | T_MEM_BITS = 2, | ||
1274 | N_MEM_VAL = 0, | ||
1275 | N_MEM_BITS = 2, | ||
1276 | NP_LOAD = 1 << 17, | ||
1277 | S_LOAD_MEM = 1 << 5, | ||
1278 | S_LOAD_CORE = 1 << 6, | ||
1279 | S_CLOCK = 1 << 3 | ||
1280 | }; | ||
1281 | |||
1282 | if (!t1_is_T1B(adapter)) | ||
1283 | return -ENODEV; /* Can't re-clock this chip. */ | ||
1284 | |||
1285 | if (mode & 2) { | ||
1286 | return 0; /* show current mode. */ | ||
1287 | } | ||
1288 | |||
1289 | if ((adapter->t1powersave & 1) == (mode & 1)) | ||
1290 | return -EALREADY; /* ASIC already running in mode. */ | ||
1291 | |||
1292 | if ((mode & 1) == HCLOCK) { | ||
1293 | M_CORE_VAL = 0x14; | ||
1294 | M_MEM_VAL = 0x18; | ||
1295 | adapter->t1powersave = HCLOCK; /* overclock */ | ||
1296 | } else { | ||
1297 | M_CORE_VAL = 0xe; | ||
1298 | M_MEM_VAL = 0x10; | ||
1299 | adapter->t1powersave = LCLOCK; /* underclock */ | ||
1300 | } | ||
1301 | |||
1302 | /* Don't interrupt this serial stream! */ | ||
1303 | spin_lock(&adapter->tpi_lock); | ||
1304 | |||
1305 | /* Initialize for ASIC core */ | ||
1306 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1307 | val |= NP_LOAD; | ||
1308 | udelay(50); | ||
1309 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1310 | udelay(50); | ||
1311 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1312 | val &= ~S_LOAD_CORE; | ||
1313 | val &= ~S_CLOCK; | ||
1314 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1315 | udelay(50); | ||
1316 | |||
1317 | /* Serial program the ASIC clock synthesizer */ | ||
1318 | bit_bang(adapter, T_CORE_VAL, T_CORE_BITS); | ||
1319 | bit_bang(adapter, N_CORE_VAL, N_CORE_BITS); | ||
1320 | bit_bang(adapter, M_CORE_VAL, M_CORE_BITS); | ||
1321 | udelay(50); | ||
1322 | |||
1323 | /* Finish ASIC core */ | ||
1324 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1325 | val |= S_LOAD_CORE; | ||
1326 | udelay(50); | ||
1327 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1328 | udelay(50); | ||
1329 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1330 | val &= ~S_LOAD_CORE; | ||
1331 | udelay(50); | ||
1332 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1333 | udelay(50); | ||
1334 | |||
1335 | /* Initialize for memory */ | ||
1336 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1337 | val |= NP_LOAD; | ||
1338 | udelay(50); | ||
1339 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1340 | udelay(50); | ||
1341 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1342 | val &= ~S_LOAD_MEM; | ||
1343 | val &= ~S_CLOCK; | ||
1344 | udelay(50); | ||
1345 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1346 | udelay(50); | ||
1347 | |||
1348 | /* Serial program the memory clock synthesizer */ | ||
1349 | bit_bang(adapter, T_MEM_VAL, T_MEM_BITS); | ||
1350 | bit_bang(adapter, N_MEM_VAL, N_MEM_BITS); | ||
1351 | bit_bang(adapter, M_MEM_VAL, M_MEM_BITS); | ||
1352 | udelay(50); | ||
1353 | |||
1354 | /* Finish memory */ | ||
1355 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1356 | val |= S_LOAD_MEM; | ||
1357 | udelay(50); | ||
1358 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1359 | udelay(50); | ||
1360 | __t1_tpi_read(adapter, A_ELMER0_GPO, &val); | ||
1361 | val &= ~S_LOAD_MEM; | ||
1362 | udelay(50); | ||
1363 | __t1_tpi_write(adapter, A_ELMER0_GPO, val); | ||
1364 | |||
1365 | spin_unlock(&adapter->tpi_lock); | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1156 | static inline void t1_sw_reset(struct pci_dev *pdev) | 1370 | static inline void t1_sw_reset(struct pci_dev *pdev) |
1157 | { | 1371 | { |
1158 | pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3); | 1372 | pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3); |