diff options
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r-- | drivers/net/cxgb3/adapter.h | 9 | ||||
-rw-r--r-- | drivers/net/cxgb3/ael1002.c | 1074 | ||||
-rw-r--r-- | drivers/net/cxgb3/common.h | 87 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_ctl_defs.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_defs.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_ioctl.h | 4 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 390 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_offload.c | 10 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_offload.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/firmware_exports.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/l2t.c | 41 | ||||
-rw-r--r-- | drivers/net/cxgb3/l2t.h | 5 | ||||
-rw-r--r-- | drivers/net/cxgb3/mc5.c | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/regs.h | 4 | ||||
-rw-r--r-- | drivers/net/cxgb3/sge.c | 112 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3_cpl.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3_hw.c | 243 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3cdev.h | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/version.h | 4 | ||||
-rw-r--r-- | drivers/net/cxgb3/vsc8211.c | 208 | ||||
-rw-r--r-- | drivers/net/cxgb3/xgmac.c | 2 |
21 files changed, 1813 insertions, 394 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 271140433b09..bc8e2413abd2 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -54,7 +54,6 @@ struct port_info { | |||
54 | struct adapter *adapter; | 54 | struct adapter *adapter; |
55 | struct vlan_group *vlan_grp; | 55 | struct vlan_group *vlan_grp; |
56 | struct sge_qset *qs; | 56 | struct sge_qset *qs; |
57 | const struct port_type_info *port_type; | ||
58 | u8 port_id; | 57 | u8 port_id; |
59 | u8 rx_csum_offload; | 58 | u8 rx_csum_offload; |
60 | u8 nqsets; | 59 | u8 nqsets; |
@@ -124,8 +123,7 @@ struct sge_rspq { /* state for an SGE response queue */ | |||
124 | dma_addr_t phys_addr; /* physical address of the ring */ | 123 | dma_addr_t phys_addr; /* physical address of the ring */ |
125 | unsigned int cntxt_id; /* SGE context id for the response q */ | 124 | unsigned int cntxt_id; /* SGE context id for the response q */ |
126 | spinlock_t lock; /* guards response processing */ | 125 | spinlock_t lock; /* guards response processing */ |
127 | struct sk_buff *rx_head; /* offload packet receive queue head */ | 126 | struct sk_buff_head rx_queue; /* offload packet receive queue */ |
128 | struct sk_buff *rx_tail; /* offload packet receive queue tail */ | ||
129 | struct sk_buff *pg_skb; /* used to build frag list in napi handler */ | 127 | struct sk_buff *pg_skb; /* used to build frag list in napi handler */ |
130 | 128 | ||
131 | unsigned long offload_pkts; | 129 | unsigned long offload_pkts; |
@@ -241,6 +239,7 @@ struct adapter { | |||
241 | unsigned int check_task_cnt; | 239 | unsigned int check_task_cnt; |
242 | struct delayed_work adap_check_task; | 240 | struct delayed_work adap_check_task; |
243 | struct work_struct ext_intr_handler_task; | 241 | struct work_struct ext_intr_handler_task; |
242 | struct work_struct fatal_error_handler_task; | ||
244 | 243 | ||
245 | struct dentry *debugfs_root; | 244 | struct dentry *debugfs_root; |
246 | 245 | ||
@@ -282,9 +281,11 @@ int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb); | |||
282 | void t3_os_ext_intr_handler(struct adapter *adapter); | 281 | void t3_os_ext_intr_handler(struct adapter *adapter); |
283 | void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, | 282 | void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, |
284 | int speed, int duplex, int fc); | 283 | int speed, int duplex, int fc); |
284 | void t3_os_phymod_changed(struct adapter *adap, int port_id); | ||
285 | 285 | ||
286 | void t3_sge_start(struct adapter *adap); | 286 | void t3_sge_start(struct adapter *adap); |
287 | void t3_sge_stop(struct adapter *adap); | 287 | void t3_sge_stop(struct adapter *adap); |
288 | void t3_stop_sge_timers(struct adapter *adap); | ||
288 | void t3_free_sge_resources(struct adapter *adap); | 289 | void t3_free_sge_resources(struct adapter *adap); |
289 | void t3_sge_err_intr_handler(struct adapter *adapter); | 290 | void t3_sge_err_intr_handler(struct adapter *adapter); |
290 | irq_handler_t t3_intr_handler(struct adapter *adap, int polling); | 291 | irq_handler_t t3_intr_handler(struct adapter *adap, int polling); |
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c index ee140e63ddc5..5c3c05da4d96 100644 --- a/drivers/net/cxgb3/ael1002.c +++ b/drivers/net/cxgb3/ael1002.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -33,17 +33,57 @@ | |||
33 | #include "regs.h" | 33 | #include "regs.h" |
34 | 34 | ||
35 | enum { | 35 | enum { |
36 | PMD_RSD = 10, /* PMA/PMD receive signal detect register */ | ||
37 | PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */ | ||
38 | PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */ | ||
39 | XS_LN_STAT = 24 /* XS lane status register */ | ||
40 | }; | ||
41 | |||
42 | enum { | ||
36 | AEL100X_TX_DISABLE = 9, | 43 | AEL100X_TX_DISABLE = 9, |
37 | AEL100X_TX_CONFIG1 = 0xc002, | 44 | AEL100X_TX_CONFIG1 = 0xc002, |
38 | AEL1002_PWR_DOWN_HI = 0xc011, | 45 | AEL1002_PWR_DOWN_HI = 0xc011, |
39 | AEL1002_PWR_DOWN_LO = 0xc012, | 46 | AEL1002_PWR_DOWN_LO = 0xc012, |
40 | AEL1002_XFI_EQL = 0xc015, | 47 | AEL1002_XFI_EQL = 0xc015, |
41 | AEL1002_LB_EN = 0xc017, | 48 | AEL1002_LB_EN = 0xc017, |
49 | AEL_OPT_SETTINGS = 0xc017, | ||
50 | AEL_I2C_CTRL = 0xc30a, | ||
51 | AEL_I2C_DATA = 0xc30b, | ||
52 | AEL_I2C_STAT = 0xc30c, | ||
53 | AEL2005_GPIO_CTRL = 0xc214, | ||
54 | AEL2005_GPIO_STAT = 0xc215, | ||
55 | }; | ||
56 | |||
57 | enum { edc_none, edc_sr, edc_twinax }; | ||
42 | 58 | ||
43 | LASI_CTRL = 0x9002, | 59 | /* PHY module I2C device address */ |
44 | LASI_STAT = 0x9005 | 60 | #define MODULE_DEV_ADDR 0xa0 |
61 | |||
62 | #define AEL2005_MODDET_IRQ 4 | ||
63 | |||
64 | struct reg_val { | ||
65 | unsigned short mmd_addr; | ||
66 | unsigned short reg_addr; | ||
67 | unsigned short clear_bits; | ||
68 | unsigned short set_bits; | ||
45 | }; | 69 | }; |
46 | 70 | ||
71 | static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) | ||
72 | { | ||
73 | int err; | ||
74 | |||
75 | for (err = 0; rv->mmd_addr && !err; rv++) { | ||
76 | if (rv->clear_bits == 0xffff) | ||
77 | err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, | ||
78 | rv->set_bits); | ||
79 | else | ||
80 | err = t3_mdio_change_bits(phy, rv->mmd_addr, | ||
81 | rv->reg_addr, rv->clear_bits, | ||
82 | rv->set_bits); | ||
83 | } | ||
84 | return err; | ||
85 | } | ||
86 | |||
47 | static void ael100x_txon(struct cphy *phy) | 87 | static void ael100x_txon(struct cphy *phy) |
48 | { | 88 | { |
49 | int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; | 89 | int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; |
@@ -84,23 +124,23 @@ static int ael1002_intr_noop(struct cphy *phy) | |||
84 | return 0; | 124 | return 0; |
85 | } | 125 | } |
86 | 126 | ||
87 | static int ael100x_get_link_status(struct cphy *phy, int *link_ok, | 127 | /* |
88 | int *speed, int *duplex, int *fc) | 128 | * Get link status for a 10GBASE-R device. |
129 | */ | ||
130 | static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, | ||
131 | int *duplex, int *fc) | ||
89 | { | 132 | { |
90 | if (link_ok) { | 133 | if (link_ok) { |
91 | unsigned int status; | 134 | unsigned int stat0, stat1, stat2; |
92 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status); | 135 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); |
93 | 136 | ||
94 | /* | 137 | if (!err) |
95 | * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it | 138 | err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1); |
96 | * once more to get the current link state. | 139 | if (!err) |
97 | */ | 140 | err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); |
98 | if (!err && !(status & BMSR_LSTATUS)) | ||
99 | err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, | ||
100 | &status); | ||
101 | if (err) | 141 | if (err) |
102 | return err; | 142 | return err; |
103 | *link_ok = !!(status & BMSR_LSTATUS); | 143 | *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; |
104 | } | 144 | } |
105 | if (speed) | 145 | if (speed) |
106 | *speed = SPEED_10000; | 146 | *speed = SPEED_10000; |
@@ -115,15 +155,18 @@ static struct cphy_ops ael1002_ops = { | |||
115 | .intr_disable = ael1002_intr_noop, | 155 | .intr_disable = ael1002_intr_noop, |
116 | .intr_clear = ael1002_intr_noop, | 156 | .intr_clear = ael1002_intr_noop, |
117 | .intr_handler = ael1002_intr_noop, | 157 | .intr_handler = ael1002_intr_noop, |
118 | .get_link_status = ael100x_get_link_status, | 158 | .get_link_status = get_link_status_r, |
119 | .power_down = ael1002_power_down, | 159 | .power_down = ael1002_power_down, |
120 | }; | 160 | }; |
121 | 161 | ||
122 | void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, | 162 | int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, |
123 | int phy_addr, const struct mdio_ops *mdio_ops) | 163 | int phy_addr, const struct mdio_ops *mdio_ops) |
124 | { | 164 | { |
125 | cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops); | 165 | cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops, |
166 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, | ||
167 | "10GBASE-R"); | ||
126 | ael100x_txon(phy); | 168 | ael100x_txon(phy); |
169 | return 0; | ||
127 | } | 170 | } |
128 | 171 | ||
129 | static int ael1006_reset(struct cphy *phy, int wait) | 172 | static int ael1006_reset(struct cphy *phy, int wait) |
@@ -131,72 +174,985 @@ static int ael1006_reset(struct cphy *phy, int wait) | |||
131 | return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); | 174 | return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); |
132 | } | 175 | } |
133 | 176 | ||
134 | static int ael1006_intr_enable(struct cphy *phy) | 177 | static int ael1006_power_down(struct cphy *phy, int enable) |
135 | { | 178 | { |
136 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); | 179 | return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, |
180 | BMCR_PDOWN, enable ? BMCR_PDOWN : 0); | ||
137 | } | 181 | } |
138 | 182 | ||
139 | static int ael1006_intr_disable(struct cphy *phy) | 183 | static struct cphy_ops ael1006_ops = { |
184 | .reset = ael1006_reset, | ||
185 | .intr_enable = t3_phy_lasi_intr_enable, | ||
186 | .intr_disable = t3_phy_lasi_intr_disable, | ||
187 | .intr_clear = t3_phy_lasi_intr_clear, | ||
188 | .intr_handler = t3_phy_lasi_intr_handler, | ||
189 | .get_link_status = get_link_status_r, | ||
190 | .power_down = ael1006_power_down, | ||
191 | }; | ||
192 | |||
193 | int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, | ||
194 | int phy_addr, const struct mdio_ops *mdio_ops) | ||
140 | { | 195 | { |
141 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); | 196 | cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops, |
197 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, | ||
198 | "10GBASE-SR"); | ||
199 | ael100x_txon(phy); | ||
200 | return 0; | ||
142 | } | 201 | } |
143 | 202 | ||
144 | static int ael1006_intr_clear(struct cphy *phy) | 203 | static int ael2005_setup_sr_edc(struct cphy *phy) |
145 | { | 204 | { |
146 | u32 val; | 205 | static struct reg_val regs[] = { |
206 | { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, | ||
207 | { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, | ||
208 | { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, | ||
209 | { 0, 0, 0, 0 } | ||
210 | }; | ||
211 | static u16 sr_edc[] = { | ||
212 | 0xcc00, 0x2ff4, | ||
213 | 0xcc01, 0x3cd4, | ||
214 | 0xcc02, 0x2015, | ||
215 | 0xcc03, 0x3105, | ||
216 | 0xcc04, 0x6524, | ||
217 | 0xcc05, 0x27ff, | ||
218 | 0xcc06, 0x300f, | ||
219 | 0xcc07, 0x2c8b, | ||
220 | 0xcc08, 0x300b, | ||
221 | 0xcc09, 0x4009, | ||
222 | 0xcc0a, 0x400e, | ||
223 | 0xcc0b, 0x2f72, | ||
224 | 0xcc0c, 0x3002, | ||
225 | 0xcc0d, 0x1002, | ||
226 | 0xcc0e, 0x2172, | ||
227 | 0xcc0f, 0x3012, | ||
228 | 0xcc10, 0x1002, | ||
229 | 0xcc11, 0x25d2, | ||
230 | 0xcc12, 0x3012, | ||
231 | 0xcc13, 0x1002, | ||
232 | 0xcc14, 0xd01e, | ||
233 | 0xcc15, 0x27d2, | ||
234 | 0xcc16, 0x3012, | ||
235 | 0xcc17, 0x1002, | ||
236 | 0xcc18, 0x2004, | ||
237 | 0xcc19, 0x3c84, | ||
238 | 0xcc1a, 0x6436, | ||
239 | 0xcc1b, 0x2007, | ||
240 | 0xcc1c, 0x3f87, | ||
241 | 0xcc1d, 0x8676, | ||
242 | 0xcc1e, 0x40b7, | ||
243 | 0xcc1f, 0xa746, | ||
244 | 0xcc20, 0x4047, | ||
245 | 0xcc21, 0x5673, | ||
246 | 0xcc22, 0x2982, | ||
247 | 0xcc23, 0x3002, | ||
248 | 0xcc24, 0x13d2, | ||
249 | 0xcc25, 0x8bbd, | ||
250 | 0xcc26, 0x2862, | ||
251 | 0xcc27, 0x3012, | ||
252 | 0xcc28, 0x1002, | ||
253 | 0xcc29, 0x2092, | ||
254 | 0xcc2a, 0x3012, | ||
255 | 0xcc2b, 0x1002, | ||
256 | 0xcc2c, 0x5cc3, | ||
257 | 0xcc2d, 0x314, | ||
258 | 0xcc2e, 0x2942, | ||
259 | 0xcc2f, 0x3002, | ||
260 | 0xcc30, 0x1002, | ||
261 | 0xcc31, 0xd019, | ||
262 | 0xcc32, 0x2032, | ||
263 | 0xcc33, 0x3012, | ||
264 | 0xcc34, 0x1002, | ||
265 | 0xcc35, 0x2a04, | ||
266 | 0xcc36, 0x3c74, | ||
267 | 0xcc37, 0x6435, | ||
268 | 0xcc38, 0x2fa4, | ||
269 | 0xcc39, 0x3cd4, | ||
270 | 0xcc3a, 0x6624, | ||
271 | 0xcc3b, 0x5563, | ||
272 | 0xcc3c, 0x2d42, | ||
273 | 0xcc3d, 0x3002, | ||
274 | 0xcc3e, 0x13d2, | ||
275 | 0xcc3f, 0x464d, | ||
276 | 0xcc40, 0x2862, | ||
277 | 0xcc41, 0x3012, | ||
278 | 0xcc42, 0x1002, | ||
279 | 0xcc43, 0x2032, | ||
280 | 0xcc44, 0x3012, | ||
281 | 0xcc45, 0x1002, | ||
282 | 0xcc46, 0x2fb4, | ||
283 | 0xcc47, 0x3cd4, | ||
284 | 0xcc48, 0x6624, | ||
285 | 0xcc49, 0x5563, | ||
286 | 0xcc4a, 0x2d42, | ||
287 | 0xcc4b, 0x3002, | ||
288 | 0xcc4c, 0x13d2, | ||
289 | 0xcc4d, 0x2ed2, | ||
290 | 0xcc4e, 0x3002, | ||
291 | 0xcc4f, 0x1002, | ||
292 | 0xcc50, 0x2fd2, | ||
293 | 0xcc51, 0x3002, | ||
294 | 0xcc52, 0x1002, | ||
295 | 0xcc53, 0x004, | ||
296 | 0xcc54, 0x2942, | ||
297 | 0xcc55, 0x3002, | ||
298 | 0xcc56, 0x1002, | ||
299 | 0xcc57, 0x2092, | ||
300 | 0xcc58, 0x3012, | ||
301 | 0xcc59, 0x1002, | ||
302 | 0xcc5a, 0x5cc3, | ||
303 | 0xcc5b, 0x317, | ||
304 | 0xcc5c, 0x2f72, | ||
305 | 0xcc5d, 0x3002, | ||
306 | 0xcc5e, 0x1002, | ||
307 | 0xcc5f, 0x2942, | ||
308 | 0xcc60, 0x3002, | ||
309 | 0xcc61, 0x1002, | ||
310 | 0xcc62, 0x22cd, | ||
311 | 0xcc63, 0x301d, | ||
312 | 0xcc64, 0x2862, | ||
313 | 0xcc65, 0x3012, | ||
314 | 0xcc66, 0x1002, | ||
315 | 0xcc67, 0x2ed2, | ||
316 | 0xcc68, 0x3002, | ||
317 | 0xcc69, 0x1002, | ||
318 | 0xcc6a, 0x2d72, | ||
319 | 0xcc6b, 0x3002, | ||
320 | 0xcc6c, 0x1002, | ||
321 | 0xcc6d, 0x628f, | ||
322 | 0xcc6e, 0x2112, | ||
323 | 0xcc6f, 0x3012, | ||
324 | 0xcc70, 0x1002, | ||
325 | 0xcc71, 0x5aa3, | ||
326 | 0xcc72, 0x2dc2, | ||
327 | 0xcc73, 0x3002, | ||
328 | 0xcc74, 0x1312, | ||
329 | 0xcc75, 0x6f72, | ||
330 | 0xcc76, 0x1002, | ||
331 | 0xcc77, 0x2807, | ||
332 | 0xcc78, 0x31a7, | ||
333 | 0xcc79, 0x20c4, | ||
334 | 0xcc7a, 0x3c24, | ||
335 | 0xcc7b, 0x6724, | ||
336 | 0xcc7c, 0x1002, | ||
337 | 0xcc7d, 0x2807, | ||
338 | 0xcc7e, 0x3187, | ||
339 | 0xcc7f, 0x20c4, | ||
340 | 0xcc80, 0x3c24, | ||
341 | 0xcc81, 0x6724, | ||
342 | 0xcc82, 0x1002, | ||
343 | 0xcc83, 0x2514, | ||
344 | 0xcc84, 0x3c64, | ||
345 | 0xcc85, 0x6436, | ||
346 | 0xcc86, 0xdff4, | ||
347 | 0xcc87, 0x6436, | ||
348 | 0xcc88, 0x1002, | ||
349 | 0xcc89, 0x40a4, | ||
350 | 0xcc8a, 0x643c, | ||
351 | 0xcc8b, 0x4016, | ||
352 | 0xcc8c, 0x8c6c, | ||
353 | 0xcc8d, 0x2b24, | ||
354 | 0xcc8e, 0x3c24, | ||
355 | 0xcc8f, 0x6435, | ||
356 | 0xcc90, 0x1002, | ||
357 | 0xcc91, 0x2b24, | ||
358 | 0xcc92, 0x3c24, | ||
359 | 0xcc93, 0x643a, | ||
360 | 0xcc94, 0x4025, | ||
361 | 0xcc95, 0x8a5a, | ||
362 | 0xcc96, 0x1002, | ||
363 | 0xcc97, 0x2731, | ||
364 | 0xcc98, 0x3011, | ||
365 | 0xcc99, 0x1001, | ||
366 | 0xcc9a, 0xc7a0, | ||
367 | 0xcc9b, 0x100, | ||
368 | 0xcc9c, 0xc502, | ||
369 | 0xcc9d, 0x53ac, | ||
370 | 0xcc9e, 0xc503, | ||
371 | 0xcc9f, 0xd5d5, | ||
372 | 0xcca0, 0xc600, | ||
373 | 0xcca1, 0x2a6d, | ||
374 | 0xcca2, 0xc601, | ||
375 | 0xcca3, 0x2a4c, | ||
376 | 0xcca4, 0xc602, | ||
377 | 0xcca5, 0x111, | ||
378 | 0xcca6, 0xc60c, | ||
379 | 0xcca7, 0x5900, | ||
380 | 0xcca8, 0xc710, | ||
381 | 0xcca9, 0x700, | ||
382 | 0xccaa, 0xc718, | ||
383 | 0xccab, 0x700, | ||
384 | 0xccac, 0xc720, | ||
385 | 0xccad, 0x4700, | ||
386 | 0xccae, 0xc801, | ||
387 | 0xccaf, 0x7f50, | ||
388 | 0xccb0, 0xc802, | ||
389 | 0xccb1, 0x7760, | ||
390 | 0xccb2, 0xc803, | ||
391 | 0xccb3, 0x7fce, | ||
392 | 0xccb4, 0xc804, | ||
393 | 0xccb5, 0x5700, | ||
394 | 0xccb6, 0xc805, | ||
395 | 0xccb7, 0x5f11, | ||
396 | 0xccb8, 0xc806, | ||
397 | 0xccb9, 0x4751, | ||
398 | 0xccba, 0xc807, | ||
399 | 0xccbb, 0x57e1, | ||
400 | 0xccbc, 0xc808, | ||
401 | 0xccbd, 0x2700, | ||
402 | 0xccbe, 0xc809, | ||
403 | 0xccbf, 0x000, | ||
404 | 0xccc0, 0xc821, | ||
405 | 0xccc1, 0x002, | ||
406 | 0xccc2, 0xc822, | ||
407 | 0xccc3, 0x014, | ||
408 | 0xccc4, 0xc832, | ||
409 | 0xccc5, 0x1186, | ||
410 | 0xccc6, 0xc847, | ||
411 | 0xccc7, 0x1e02, | ||
412 | 0xccc8, 0xc013, | ||
413 | 0xccc9, 0xf341, | ||
414 | 0xccca, 0xc01a, | ||
415 | 0xcccb, 0x446, | ||
416 | 0xcccc, 0xc024, | ||
417 | 0xcccd, 0x1000, | ||
418 | 0xccce, 0xc025, | ||
419 | 0xcccf, 0xa00, | ||
420 | 0xccd0, 0xc026, | ||
421 | 0xccd1, 0xc0c, | ||
422 | 0xccd2, 0xc027, | ||
423 | 0xccd3, 0xc0c, | ||
424 | 0xccd4, 0xc029, | ||
425 | 0xccd5, 0x0a0, | ||
426 | 0xccd6, 0xc030, | ||
427 | 0xccd7, 0xa00, | ||
428 | 0xccd8, 0xc03c, | ||
429 | 0xccd9, 0x01c, | ||
430 | 0xccda, 0xc005, | ||
431 | 0xccdb, 0x7a06, | ||
432 | 0xccdc, 0x000, | ||
433 | 0xccdd, 0x2731, | ||
434 | 0xccde, 0x3011, | ||
435 | 0xccdf, 0x1001, | ||
436 | 0xcce0, 0xc620, | ||
437 | 0xcce1, 0x000, | ||
438 | 0xcce2, 0xc621, | ||
439 | 0xcce3, 0x03f, | ||
440 | 0xcce4, 0xc622, | ||
441 | 0xcce5, 0x000, | ||
442 | 0xcce6, 0xc623, | ||
443 | 0xcce7, 0x000, | ||
444 | 0xcce8, 0xc624, | ||
445 | 0xcce9, 0x000, | ||
446 | 0xccea, 0xc625, | ||
447 | 0xcceb, 0x000, | ||
448 | 0xccec, 0xc627, | ||
449 | 0xcced, 0x000, | ||
450 | 0xccee, 0xc628, | ||
451 | 0xccef, 0x000, | ||
452 | 0xccf0, 0xc62c, | ||
453 | 0xccf1, 0x000, | ||
454 | 0xccf2, 0x000, | ||
455 | 0xccf3, 0x2806, | ||
456 | 0xccf4, 0x3cb6, | ||
457 | 0xccf5, 0xc161, | ||
458 | 0xccf6, 0x6134, | ||
459 | 0xccf7, 0x6135, | ||
460 | 0xccf8, 0x5443, | ||
461 | 0xccf9, 0x303, | ||
462 | 0xccfa, 0x6524, | ||
463 | 0xccfb, 0x00b, | ||
464 | 0xccfc, 0x1002, | ||
465 | 0xccfd, 0x2104, | ||
466 | 0xccfe, 0x3c24, | ||
467 | 0xccff, 0x2105, | ||
468 | 0xcd00, 0x3805, | ||
469 | 0xcd01, 0x6524, | ||
470 | 0xcd02, 0xdff4, | ||
471 | 0xcd03, 0x4005, | ||
472 | 0xcd04, 0x6524, | ||
473 | 0xcd05, 0x1002, | ||
474 | 0xcd06, 0x5dd3, | ||
475 | 0xcd07, 0x306, | ||
476 | 0xcd08, 0x2ff7, | ||
477 | 0xcd09, 0x38f7, | ||
478 | 0xcd0a, 0x60b7, | ||
479 | 0xcd0b, 0xdffd, | ||
480 | 0xcd0c, 0x00a, | ||
481 | 0xcd0d, 0x1002, | ||
482 | 0xcd0e, 0 | ||
483 | }; | ||
484 | int i, err; | ||
485 | |||
486 | err = set_phy_regs(phy, regs); | ||
487 | if (err) | ||
488 | return err; | ||
147 | 489 | ||
148 | return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); | 490 | msleep(50); |
491 | |||
492 | for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) | ||
493 | err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], | ||
494 | sr_edc[i + 1]); | ||
495 | if (!err) | ||
496 | phy->priv = edc_sr; | ||
497 | return err; | ||
149 | } | 498 | } |
150 | 499 | ||
151 | static int ael1006_intr_handler(struct cphy *phy) | 500 | static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) |
152 | { | 501 | { |
153 | unsigned int status; | 502 | static struct reg_val regs[] = { |
154 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); | 503 | { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 }, |
504 | { 0, 0, 0, 0 } | ||
505 | }; | ||
506 | static struct reg_val preemphasis[] = { | ||
507 | { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 }, | ||
508 | { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 }, | ||
509 | { 0, 0, 0, 0 } | ||
510 | }; | ||
511 | static u16 twinax_edc[] = { | ||
512 | 0xcc00, 0x4009, | ||
513 | 0xcc01, 0x27ff, | ||
514 | 0xcc02, 0x300f, | ||
515 | 0xcc03, 0x40aa, | ||
516 | 0xcc04, 0x401c, | ||
517 | 0xcc05, 0x401e, | ||
518 | 0xcc06, 0x2ff4, | ||
519 | 0xcc07, 0x3cd4, | ||
520 | 0xcc08, 0x2035, | ||
521 | 0xcc09, 0x3145, | ||
522 | 0xcc0a, 0x6524, | ||
523 | 0xcc0b, 0x26a2, | ||
524 | 0xcc0c, 0x3012, | ||
525 | 0xcc0d, 0x1002, | ||
526 | 0xcc0e, 0x29c2, | ||
527 | 0xcc0f, 0x3002, | ||
528 | 0xcc10, 0x1002, | ||
529 | 0xcc11, 0x2072, | ||
530 | 0xcc12, 0x3012, | ||
531 | 0xcc13, 0x1002, | ||
532 | 0xcc14, 0x22cd, | ||
533 | 0xcc15, 0x301d, | ||
534 | 0xcc16, 0x2e52, | ||
535 | 0xcc17, 0x3012, | ||
536 | 0xcc18, 0x1002, | ||
537 | 0xcc19, 0x28e2, | ||
538 | 0xcc1a, 0x3002, | ||
539 | 0xcc1b, 0x1002, | ||
540 | 0xcc1c, 0x628f, | ||
541 | 0xcc1d, 0x2ac2, | ||
542 | 0xcc1e, 0x3012, | ||
543 | 0xcc1f, 0x1002, | ||
544 | 0xcc20, 0x5553, | ||
545 | 0xcc21, 0x2ae2, | ||
546 | 0xcc22, 0x3002, | ||
547 | 0xcc23, 0x1302, | ||
548 | 0xcc24, 0x401e, | ||
549 | 0xcc25, 0x2be2, | ||
550 | 0xcc26, 0x3012, | ||
551 | 0xcc27, 0x1002, | ||
552 | 0xcc28, 0x2da2, | ||
553 | 0xcc29, 0x3012, | ||
554 | 0xcc2a, 0x1002, | ||
555 | 0xcc2b, 0x2ba2, | ||
556 | 0xcc2c, 0x3002, | ||
557 | 0xcc2d, 0x1002, | ||
558 | 0xcc2e, 0x5ee3, | ||
559 | 0xcc2f, 0x305, | ||
560 | 0xcc30, 0x400e, | ||
561 | 0xcc31, 0x2bc2, | ||
562 | 0xcc32, 0x3002, | ||
563 | 0xcc33, 0x1002, | ||
564 | 0xcc34, 0x2b82, | ||
565 | 0xcc35, 0x3012, | ||
566 | 0xcc36, 0x1002, | ||
567 | 0xcc37, 0x5663, | ||
568 | 0xcc38, 0x302, | ||
569 | 0xcc39, 0x401e, | ||
570 | 0xcc3a, 0x6f72, | ||
571 | 0xcc3b, 0x1002, | ||
572 | 0xcc3c, 0x628f, | ||
573 | 0xcc3d, 0x2be2, | ||
574 | 0xcc3e, 0x3012, | ||
575 | 0xcc3f, 0x1002, | ||
576 | 0xcc40, 0x22cd, | ||
577 | 0xcc41, 0x301d, | ||
578 | 0xcc42, 0x2e52, | ||
579 | 0xcc43, 0x3012, | ||
580 | 0xcc44, 0x1002, | ||
581 | 0xcc45, 0x2522, | ||
582 | 0xcc46, 0x3012, | ||
583 | 0xcc47, 0x1002, | ||
584 | 0xcc48, 0x2da2, | ||
585 | 0xcc49, 0x3012, | ||
586 | 0xcc4a, 0x1002, | ||
587 | 0xcc4b, 0x2ca2, | ||
588 | 0xcc4c, 0x3012, | ||
589 | 0xcc4d, 0x1002, | ||
590 | 0xcc4e, 0x2fa4, | ||
591 | 0xcc4f, 0x3cd4, | ||
592 | 0xcc50, 0x6624, | ||
593 | 0xcc51, 0x410b, | ||
594 | 0xcc52, 0x56b3, | ||
595 | 0xcc53, 0x3c4, | ||
596 | 0xcc54, 0x2fb2, | ||
597 | 0xcc55, 0x3002, | ||
598 | 0xcc56, 0x1002, | ||
599 | 0xcc57, 0x220b, | ||
600 | 0xcc58, 0x303b, | ||
601 | 0xcc59, 0x56b3, | ||
602 | 0xcc5a, 0x3c3, | ||
603 | 0xcc5b, 0x866b, | ||
604 | 0xcc5c, 0x400c, | ||
605 | 0xcc5d, 0x23a2, | ||
606 | 0xcc5e, 0x3012, | ||
607 | 0xcc5f, 0x1002, | ||
608 | 0xcc60, 0x2da2, | ||
609 | 0xcc61, 0x3012, | ||
610 | 0xcc62, 0x1002, | ||
611 | 0xcc63, 0x2ca2, | ||
612 | 0xcc64, 0x3012, | ||
613 | 0xcc65, 0x1002, | ||
614 | 0xcc66, 0x2fb4, | ||
615 | 0xcc67, 0x3cd4, | ||
616 | 0xcc68, 0x6624, | ||
617 | 0xcc69, 0x56b3, | ||
618 | 0xcc6a, 0x3c3, | ||
619 | 0xcc6b, 0x866b, | ||
620 | 0xcc6c, 0x401c, | ||
621 | 0xcc6d, 0x2205, | ||
622 | 0xcc6e, 0x3035, | ||
623 | 0xcc6f, 0x5b53, | ||
624 | 0xcc70, 0x2c52, | ||
625 | 0xcc71, 0x3002, | ||
626 | 0xcc72, 0x13c2, | ||
627 | 0xcc73, 0x5cc3, | ||
628 | 0xcc74, 0x317, | ||
629 | 0xcc75, 0x2522, | ||
630 | 0xcc76, 0x3012, | ||
631 | 0xcc77, 0x1002, | ||
632 | 0xcc78, 0x2da2, | ||
633 | 0xcc79, 0x3012, | ||
634 | 0xcc7a, 0x1002, | ||
635 | 0xcc7b, 0x2b82, | ||
636 | 0xcc7c, 0x3012, | ||
637 | 0xcc7d, 0x1002, | ||
638 | 0xcc7e, 0x5663, | ||
639 | 0xcc7f, 0x303, | ||
640 | 0xcc80, 0x401e, | ||
641 | 0xcc81, 0x004, | ||
642 | 0xcc82, 0x2c42, | ||
643 | 0xcc83, 0x3012, | ||
644 | 0xcc84, 0x1002, | ||
645 | 0xcc85, 0x6f72, | ||
646 | 0xcc86, 0x1002, | ||
647 | 0xcc87, 0x628f, | ||
648 | 0xcc88, 0x2304, | ||
649 | 0xcc89, 0x3c84, | ||
650 | 0xcc8a, 0x6436, | ||
651 | 0xcc8b, 0xdff4, | ||
652 | 0xcc8c, 0x6436, | ||
653 | 0xcc8d, 0x2ff5, | ||
654 | 0xcc8e, 0x3005, | ||
655 | 0xcc8f, 0x8656, | ||
656 | 0xcc90, 0xdfba, | ||
657 | 0xcc91, 0x56a3, | ||
658 | 0xcc92, 0xd05a, | ||
659 | 0xcc93, 0x21c2, | ||
660 | 0xcc94, 0x3012, | ||
661 | 0xcc95, 0x1392, | ||
662 | 0xcc96, 0xd05a, | ||
663 | 0xcc97, 0x56a3, | ||
664 | 0xcc98, 0xdfba, | ||
665 | 0xcc99, 0x383, | ||
666 | 0xcc9a, 0x6f72, | ||
667 | 0xcc9b, 0x1002, | ||
668 | 0xcc9c, 0x28c5, | ||
669 | 0xcc9d, 0x3005, | ||
670 | 0xcc9e, 0x4178, | ||
671 | 0xcc9f, 0x5653, | ||
672 | 0xcca0, 0x384, | ||
673 | 0xcca1, 0x22b2, | ||
674 | 0xcca2, 0x3012, | ||
675 | 0xcca3, 0x1002, | ||
676 | 0xcca4, 0x2be5, | ||
677 | 0xcca5, 0x3005, | ||
678 | 0xcca6, 0x41e8, | ||
679 | 0xcca7, 0x5653, | ||
680 | 0xcca8, 0x382, | ||
681 | 0xcca9, 0x002, | ||
682 | 0xccaa, 0x4258, | ||
683 | 0xccab, 0x2474, | ||
684 | 0xccac, 0x3c84, | ||
685 | 0xccad, 0x6437, | ||
686 | 0xccae, 0xdff4, | ||
687 | 0xccaf, 0x6437, | ||
688 | 0xccb0, 0x2ff5, | ||
689 | 0xccb1, 0x3c05, | ||
690 | 0xccb2, 0x8757, | ||
691 | 0xccb3, 0xb888, | ||
692 | 0xccb4, 0x9787, | ||
693 | 0xccb5, 0xdff4, | ||
694 | 0xccb6, 0x6724, | ||
695 | 0xccb7, 0x866a, | ||
696 | 0xccb8, 0x6f72, | ||
697 | 0xccb9, 0x1002, | ||
698 | 0xccba, 0x2d01, | ||
699 | 0xccbb, 0x3011, | ||
700 | 0xccbc, 0x1001, | ||
701 | 0xccbd, 0xc620, | ||
702 | 0xccbe, 0x14e5, | ||
703 | 0xccbf, 0xc621, | ||
704 | 0xccc0, 0xc53d, | ||
705 | 0xccc1, 0xc622, | ||
706 | 0xccc2, 0x3cbe, | ||
707 | 0xccc3, 0xc623, | ||
708 | 0xccc4, 0x4452, | ||
709 | 0xccc5, 0xc624, | ||
710 | 0xccc6, 0xc5c5, | ||
711 | 0xccc7, 0xc625, | ||
712 | 0xccc8, 0xe01e, | ||
713 | 0xccc9, 0xc627, | ||
714 | 0xccca, 0x000, | ||
715 | 0xcccb, 0xc628, | ||
716 | 0xcccc, 0x000, | ||
717 | 0xcccd, 0xc62b, | ||
718 | 0xccce, 0x000, | ||
719 | 0xcccf, 0xc62c, | ||
720 | 0xccd0, 0x000, | ||
721 | 0xccd1, 0x000, | ||
722 | 0xccd2, 0x2d01, | ||
723 | 0xccd3, 0x3011, | ||
724 | 0xccd4, 0x1001, | ||
725 | 0xccd5, 0xc620, | ||
726 | 0xccd6, 0x000, | ||
727 | 0xccd7, 0xc621, | ||
728 | 0xccd8, 0x000, | ||
729 | 0xccd9, 0xc622, | ||
730 | 0xccda, 0x0ce, | ||
731 | 0xccdb, 0xc623, | ||
732 | 0xccdc, 0x07f, | ||
733 | 0xccdd, 0xc624, | ||
734 | 0xccde, 0x032, | ||
735 | 0xccdf, 0xc625, | ||
736 | 0xcce0, 0x000, | ||
737 | 0xcce1, 0xc627, | ||
738 | 0xcce2, 0x000, | ||
739 | 0xcce3, 0xc628, | ||
740 | 0xcce4, 0x000, | ||
741 | 0xcce5, 0xc62b, | ||
742 | 0xcce6, 0x000, | ||
743 | 0xcce7, 0xc62c, | ||
744 | 0xcce8, 0x000, | ||
745 | 0xcce9, 0x000, | ||
746 | 0xccea, 0x2d01, | ||
747 | 0xcceb, 0x3011, | ||
748 | 0xccec, 0x1001, | ||
749 | 0xcced, 0xc502, | ||
750 | 0xccee, 0x609f, | ||
751 | 0xccef, 0xc600, | ||
752 | 0xccf0, 0x2a6e, | ||
753 | 0xccf1, 0xc601, | ||
754 | 0xccf2, 0x2a2c, | ||
755 | 0xccf3, 0xc60c, | ||
756 | 0xccf4, 0x5400, | ||
757 | 0xccf5, 0xc710, | ||
758 | 0xccf6, 0x700, | ||
759 | 0xccf7, 0xc718, | ||
760 | 0xccf8, 0x700, | ||
761 | 0xccf9, 0xc720, | ||
762 | 0xccfa, 0x4700, | ||
763 | 0xccfb, 0xc728, | ||
764 | 0xccfc, 0x700, | ||
765 | 0xccfd, 0xc729, | ||
766 | 0xccfe, 0x1207, | ||
767 | 0xccff, 0xc801, | ||
768 | 0xcd00, 0x7f50, | ||
769 | 0xcd01, 0xc802, | ||
770 | 0xcd02, 0x7760, | ||
771 | 0xcd03, 0xc803, | ||
772 | 0xcd04, 0x7fce, | ||
773 | 0xcd05, 0xc804, | ||
774 | 0xcd06, 0x520e, | ||
775 | 0xcd07, 0xc805, | ||
776 | 0xcd08, 0x5c11, | ||
777 | 0xcd09, 0xc806, | ||
778 | 0xcd0a, 0x3c51, | ||
779 | 0xcd0b, 0xc807, | ||
780 | 0xcd0c, 0x4061, | ||
781 | 0xcd0d, 0xc808, | ||
782 | 0xcd0e, 0x49c1, | ||
783 | 0xcd0f, 0xc809, | ||
784 | 0xcd10, 0x3840, | ||
785 | 0xcd11, 0xc80a, | ||
786 | 0xcd12, 0x000, | ||
787 | 0xcd13, 0xc821, | ||
788 | 0xcd14, 0x002, | ||
789 | 0xcd15, 0xc822, | ||
790 | 0xcd16, 0x046, | ||
791 | 0xcd17, 0xc844, | ||
792 | 0xcd18, 0x182f, | ||
793 | 0xcd19, 0xc013, | ||
794 | 0xcd1a, 0xf341, | ||
795 | 0xcd1b, 0xc01a, | ||
796 | 0xcd1c, 0x446, | ||
797 | 0xcd1d, 0xc024, | ||
798 | 0xcd1e, 0x1000, | ||
799 | 0xcd1f, 0xc025, | ||
800 | 0xcd20, 0xa00, | ||
801 | 0xcd21, 0xc026, | ||
802 | 0xcd22, 0xc0c, | ||
803 | 0xcd23, 0xc027, | ||
804 | 0xcd24, 0xc0c, | ||
805 | 0xcd25, 0xc029, | ||
806 | 0xcd26, 0x0a0, | ||
807 | 0xcd27, 0xc030, | ||
808 | 0xcd28, 0xa00, | ||
809 | 0xcd29, 0xc03c, | ||
810 | 0xcd2a, 0x01c, | ||
811 | 0xcd2b, 0x000, | ||
812 | 0xcd2c, 0x2b84, | ||
813 | 0xcd2d, 0x3c74, | ||
814 | 0xcd2e, 0x6435, | ||
815 | 0xcd2f, 0xdff4, | ||
816 | 0xcd30, 0x6435, | ||
817 | 0xcd31, 0x2806, | ||
818 | 0xcd32, 0x3006, | ||
819 | 0xcd33, 0x8565, | ||
820 | 0xcd34, 0x2b24, | ||
821 | 0xcd35, 0x3c24, | ||
822 | 0xcd36, 0x6436, | ||
823 | 0xcd37, 0x1002, | ||
824 | 0xcd38, 0x2b24, | ||
825 | 0xcd39, 0x3c24, | ||
826 | 0xcd3a, 0x6436, | ||
827 | 0xcd3b, 0x4045, | ||
828 | 0xcd3c, 0x8656, | ||
829 | 0xcd3d, 0x1002, | ||
830 | 0xcd3e, 0x2807, | ||
831 | 0xcd3f, 0x31a7, | ||
832 | 0xcd40, 0x20c4, | ||
833 | 0xcd41, 0x3c24, | ||
834 | 0xcd42, 0x6724, | ||
835 | 0xcd43, 0x1002, | ||
836 | 0xcd44, 0x2807, | ||
837 | 0xcd45, 0x3187, | ||
838 | 0xcd46, 0x20c4, | ||
839 | 0xcd47, 0x3c24, | ||
840 | 0xcd48, 0x6724, | ||
841 | 0xcd49, 0x1002, | ||
842 | 0xcd4a, 0x2514, | ||
843 | 0xcd4b, 0x3c64, | ||
844 | 0xcd4c, 0x6436, | ||
845 | 0xcd4d, 0xdff4, | ||
846 | 0xcd4e, 0x6436, | ||
847 | 0xcd4f, 0x1002, | ||
848 | 0xcd50, 0x2806, | ||
849 | 0xcd51, 0x3cb6, | ||
850 | 0xcd52, 0xc161, | ||
851 | 0xcd53, 0x6134, | ||
852 | 0xcd54, 0x6135, | ||
853 | 0xcd55, 0x5443, | ||
854 | 0xcd56, 0x303, | ||
855 | 0xcd57, 0x6524, | ||
856 | 0xcd58, 0x00b, | ||
857 | 0xcd59, 0x1002, | ||
858 | 0xcd5a, 0xd019, | ||
859 | 0xcd5b, 0x2104, | ||
860 | 0xcd5c, 0x3c24, | ||
861 | 0xcd5d, 0x2105, | ||
862 | 0xcd5e, 0x3805, | ||
863 | 0xcd5f, 0x6524, | ||
864 | 0xcd60, 0xdff4, | ||
865 | 0xcd61, 0x4005, | ||
866 | 0xcd62, 0x6524, | ||
867 | 0xcd63, 0x2e8d, | ||
868 | 0xcd64, 0x303d, | ||
869 | 0xcd65, 0x5dd3, | ||
870 | 0xcd66, 0x306, | ||
871 | 0xcd67, 0x2ff7, | ||
872 | 0xcd68, 0x38f7, | ||
873 | 0xcd69, 0x60b7, | ||
874 | 0xcd6a, 0xdffd, | ||
875 | 0xcd6b, 0x00a, | ||
876 | 0xcd6c, 0x1002, | ||
877 | 0xcd6d, 0 | ||
878 | }; | ||
879 | int i, err; | ||
155 | 880 | ||
881 | err = set_phy_regs(phy, regs); | ||
882 | if (!err && modtype == phy_modtype_twinax_long) | ||
883 | err = set_phy_regs(phy, preemphasis); | ||
156 | if (err) | 884 | if (err) |
157 | return err; | 885 | return err; |
158 | return (status & 1) ? cphy_cause_link_change : 0; | 886 | |
887 | msleep(50); | ||
888 | |||
889 | for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) | ||
890 | err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], | ||
891 | twinax_edc[i + 1]); | ||
892 | if (!err) | ||
893 | phy->priv = edc_twinax; | ||
894 | return err; | ||
159 | } | 895 | } |
160 | 896 | ||
161 | static int ael1006_power_down(struct cphy *phy, int enable) | 897 | static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) |
162 | { | 898 | { |
163 | return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, | 899 | int i, err; |
164 | BMCR_PDOWN, enable ? BMCR_PDOWN : 0); | 900 | unsigned int stat, data; |
901 | |||
902 | err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, | ||
903 | (dev_addr << 8) | (1 << 8) | word_addr); | ||
904 | if (err) | ||
905 | return err; | ||
906 | |||
907 | for (i = 0; i < 5; i++) { | ||
908 | msleep(1); | ||
909 | err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); | ||
910 | if (err) | ||
911 | return err; | ||
912 | if ((stat & 3) == 1) { | ||
913 | err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, | ||
914 | &data); | ||
915 | if (err) | ||
916 | return err; | ||
917 | return data >> 8; | ||
918 | } | ||
919 | } | ||
920 | CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n", | ||
921 | phy->addr, word_addr); | ||
922 | return -ETIMEDOUT; | ||
165 | } | 923 | } |
166 | 924 | ||
167 | static struct cphy_ops ael1006_ops = { | 925 | static int get_module_type(struct cphy *phy, int delay_ms) |
168 | .reset = ael1006_reset, | 926 | { |
169 | .intr_enable = ael1006_intr_enable, | 927 | int v; |
170 | .intr_disable = ael1006_intr_disable, | 928 | unsigned int stat; |
171 | .intr_clear = ael1006_intr_clear, | 929 | |
172 | .intr_handler = ael1006_intr_handler, | 930 | v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat); |
173 | .get_link_status = ael100x_get_link_status, | 931 | if (v) |
174 | .power_down = ael1006_power_down, | 932 | return v; |
933 | |||
934 | if (stat & (1 << 8)) /* module absent */ | ||
935 | return phy_modtype_none; | ||
936 | |||
937 | if (delay_ms) | ||
938 | msleep(delay_ms); | ||
939 | |||
940 | /* see SFF-8472 for below */ | ||
941 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3); | ||
942 | if (v < 0) | ||
943 | return v; | ||
944 | |||
945 | if (v == 0x10) | ||
946 | return phy_modtype_sr; | ||
947 | if (v == 0x20) | ||
948 | return phy_modtype_lr; | ||
949 | if (v == 0x40) | ||
950 | return phy_modtype_lrm; | ||
951 | |||
952 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6); | ||
953 | if (v < 0) | ||
954 | return v; | ||
955 | if (v != 4) | ||
956 | goto unknown; | ||
957 | |||
958 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10); | ||
959 | if (v < 0) | ||
960 | return v; | ||
961 | |||
962 | if (v & 0x80) { | ||
963 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); | ||
964 | if (v < 0) | ||
965 | return v; | ||
966 | return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax; | ||
967 | } | ||
968 | unknown: | ||
969 | return phy_modtype_unknown; | ||
970 | } | ||
971 | |||
972 | static int ael2005_intr_enable(struct cphy *phy) | ||
973 | { | ||
974 | int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200); | ||
975 | return err ? err : t3_phy_lasi_intr_enable(phy); | ||
976 | } | ||
977 | |||
978 | static int ael2005_intr_disable(struct cphy *phy) | ||
979 | { | ||
980 | int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100); | ||
981 | return err ? err : t3_phy_lasi_intr_disable(phy); | ||
982 | } | ||
983 | |||
984 | static int ael2005_intr_clear(struct cphy *phy) | ||
985 | { | ||
986 | int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00); | ||
987 | return err ? err : t3_phy_lasi_intr_clear(phy); | ||
988 | } | ||
989 | |||
990 | static int ael2005_reset(struct cphy *phy, int wait) | ||
991 | { | ||
992 | static struct reg_val regs0[] = { | ||
993 | { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, | ||
994 | { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, | ||
995 | { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, | ||
996 | { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, | ||
997 | { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, | ||
998 | { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, | ||
999 | { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, | ||
1000 | { 0, 0, 0, 0 } | ||
1001 | }; | ||
1002 | static struct reg_val regs1[] = { | ||
1003 | { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, | ||
1004 | { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, | ||
1005 | { 0, 0, 0, 0 } | ||
1006 | }; | ||
1007 | |||
1008 | int err, lasi_ctrl; | ||
1009 | |||
1010 | err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); | ||
1011 | if (err) | ||
1012 | return err; | ||
1013 | |||
1014 | err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); | ||
1015 | if (err) | ||
1016 | return err; | ||
1017 | |||
1018 | msleep(125); | ||
1019 | phy->priv = edc_none; | ||
1020 | err = set_phy_regs(phy, regs0); | ||
1021 | if (err) | ||
1022 | return err; | ||
1023 | |||
1024 | msleep(50); | ||
1025 | |||
1026 | err = get_module_type(phy, 0); | ||
1027 | if (err < 0) | ||
1028 | return err; | ||
1029 | phy->modtype = err; | ||
1030 | |||
1031 | if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) | ||
1032 | err = ael2005_setup_twinax_edc(phy, err); | ||
1033 | else | ||
1034 | err = ael2005_setup_sr_edc(phy); | ||
1035 | if (err) | ||
1036 | return err; | ||
1037 | |||
1038 | err = set_phy_regs(phy, regs1); | ||
1039 | if (err) | ||
1040 | return err; | ||
1041 | |||
1042 | /* reset wipes out interrupts, reenable them if they were on */ | ||
1043 | if (lasi_ctrl & 1) | ||
1044 | err = ael2005_intr_enable(phy); | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | static int ael2005_intr_handler(struct cphy *phy) | ||
1049 | { | ||
1050 | unsigned int stat; | ||
1051 | int ret, edc_needed, cause = 0; | ||
1052 | |||
1053 | ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat); | ||
1054 | if (ret) | ||
1055 | return ret; | ||
1056 | |||
1057 | if (stat & AEL2005_MODDET_IRQ) { | ||
1058 | ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, | ||
1059 | 0xd00); | ||
1060 | if (ret) | ||
1061 | return ret; | ||
1062 | |||
1063 | /* modules have max 300 ms init time after hot plug */ | ||
1064 | ret = get_module_type(phy, 300); | ||
1065 | if (ret < 0) | ||
1066 | return ret; | ||
1067 | |||
1068 | phy->modtype = ret; | ||
1069 | if (ret == phy_modtype_none) | ||
1070 | edc_needed = phy->priv; /* on unplug retain EDC */ | ||
1071 | else if (ret == phy_modtype_twinax || | ||
1072 | ret == phy_modtype_twinax_long) | ||
1073 | edc_needed = edc_twinax; | ||
1074 | else | ||
1075 | edc_needed = edc_sr; | ||
1076 | |||
1077 | if (edc_needed != phy->priv) { | ||
1078 | ret = ael2005_reset(phy, 0); | ||
1079 | return ret ? ret : cphy_cause_module_change; | ||
1080 | } | ||
1081 | cause = cphy_cause_module_change; | ||
1082 | } | ||
1083 | |||
1084 | ret = t3_phy_lasi_intr_handler(phy); | ||
1085 | if (ret < 0) | ||
1086 | return ret; | ||
1087 | |||
1088 | ret |= cause; | ||
1089 | return ret ? ret : cphy_cause_link_change; | ||
1090 | } | ||
1091 | |||
1092 | static struct cphy_ops ael2005_ops = { | ||
1093 | .reset = ael2005_reset, | ||
1094 | .intr_enable = ael2005_intr_enable, | ||
1095 | .intr_disable = ael2005_intr_disable, | ||
1096 | .intr_clear = ael2005_intr_clear, | ||
1097 | .intr_handler = ael2005_intr_handler, | ||
1098 | .get_link_status = get_link_status_r, | ||
1099 | .power_down = ael1002_power_down, | ||
175 | }; | 1100 | }; |
176 | 1101 | ||
177 | void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, | 1102 | int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, |
178 | int phy_addr, const struct mdio_ops *mdio_ops) | 1103 | int phy_addr, const struct mdio_ops *mdio_ops) |
179 | { | 1104 | { |
180 | cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops); | 1105 | cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops, |
181 | ael100x_txon(phy); | 1106 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | |
1107 | SUPPORTED_IRQ, "10GBASE-R"); | ||
1108 | msleep(125); | ||
1109 | return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, | ||
1110 | 1 << 5); | ||
1111 | } | ||
1112 | |||
1113 | /* | ||
1114 | * Get link status for a 10GBASE-X device. | ||
1115 | */ | ||
1116 | static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, | ||
1117 | int *duplex, int *fc) | ||
1118 | { | ||
1119 | if (link_ok) { | ||
1120 | unsigned int stat0, stat1, stat2; | ||
1121 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); | ||
1122 | |||
1123 | if (!err) | ||
1124 | err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1); | ||
1125 | if (!err) | ||
1126 | err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); | ||
1127 | if (err) | ||
1128 | return err; | ||
1129 | *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; | ||
1130 | } | ||
1131 | if (speed) | ||
1132 | *speed = SPEED_10000; | ||
1133 | if (duplex) | ||
1134 | *duplex = DUPLEX_FULL; | ||
1135 | return 0; | ||
182 | } | 1136 | } |
183 | 1137 | ||
184 | static struct cphy_ops qt2045_ops = { | 1138 | static struct cphy_ops qt2045_ops = { |
185 | .reset = ael1006_reset, | 1139 | .reset = ael1006_reset, |
186 | .intr_enable = ael1006_intr_enable, | 1140 | .intr_enable = t3_phy_lasi_intr_enable, |
187 | .intr_disable = ael1006_intr_disable, | 1141 | .intr_disable = t3_phy_lasi_intr_disable, |
188 | .intr_clear = ael1006_intr_clear, | 1142 | .intr_clear = t3_phy_lasi_intr_clear, |
189 | .intr_handler = ael1006_intr_handler, | 1143 | .intr_handler = t3_phy_lasi_intr_handler, |
190 | .get_link_status = ael100x_get_link_status, | 1144 | .get_link_status = get_link_status_x, |
191 | .power_down = ael1006_power_down, | 1145 | .power_down = ael1006_power_down, |
192 | }; | 1146 | }; |
193 | 1147 | ||
194 | void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, | 1148 | int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, |
195 | int phy_addr, const struct mdio_ops *mdio_ops) | 1149 | int phy_addr, const struct mdio_ops *mdio_ops) |
196 | { | 1150 | { |
197 | unsigned int stat; | 1151 | unsigned int stat; |
198 | 1152 | ||
199 | cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops); | 1153 | cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops, |
1154 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, | ||
1155 | "10GBASE-CX4"); | ||
200 | 1156 | ||
201 | /* | 1157 | /* |
202 | * Some cards where the PHY is supposed to be at address 0 actually | 1158 | * Some cards where the PHY is supposed to be at address 0 actually |
@@ -205,6 +1161,7 @@ void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, | |||
205 | if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && | 1161 | if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && |
206 | stat == 0xffff) | 1162 | stat == 0xffff) |
207 | phy->addr = 1; | 1163 | phy->addr = 1; |
1164 | return 0; | ||
208 | } | 1165 | } |
209 | 1166 | ||
210 | static int xaui_direct_reset(struct cphy *phy, int wait) | 1167 | static int xaui_direct_reset(struct cphy *phy, int wait) |
@@ -250,8 +1207,11 @@ static struct cphy_ops xaui_direct_ops = { | |||
250 | .power_down = xaui_direct_power_down, | 1207 | .power_down = xaui_direct_power_down, |
251 | }; | 1208 | }; |
252 | 1209 | ||
253 | void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, | 1210 | int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, |
254 | int phy_addr, const struct mdio_ops *mdio_ops) | 1211 | int phy_addr, const struct mdio_ops *mdio_ops) |
255 | { | 1212 | { |
256 | cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops); | 1213 | cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, |
1214 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, | ||
1215 | "10GBASE-CX4"); | ||
1216 | return 0; | ||
257 | } | 1217 | } |
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 9ecf8a6dc97f..e312d315a42d 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -193,22 +193,13 @@ struct mdio_ops { | |||
193 | struct adapter_info { | 193 | struct adapter_info { |
194 | unsigned char nports; /* # of ports */ | 194 | unsigned char nports; /* # of ports */ |
195 | unsigned char phy_base_addr; /* MDIO PHY base address */ | 195 | unsigned char phy_base_addr; /* MDIO PHY base address */ |
196 | unsigned char mdien; | ||
197 | unsigned char mdiinv; | ||
198 | unsigned int gpio_out; /* GPIO output settings */ | 196 | unsigned int gpio_out; /* GPIO output settings */ |
199 | unsigned int gpio_intr; /* GPIO IRQ enable mask */ | 197 | unsigned char gpio_intr[MAX_NPORTS]; /* GPIO PHY IRQ pins */ |
200 | unsigned long caps; /* adapter capabilities */ | 198 | unsigned long caps; /* adapter capabilities */ |
201 | const struct mdio_ops *mdio_ops; /* MDIO operations */ | 199 | const struct mdio_ops *mdio_ops; /* MDIO operations */ |
202 | const char *desc; /* product description */ | 200 | const char *desc; /* product description */ |
203 | }; | 201 | }; |
204 | 202 | ||
205 | struct port_type_info { | ||
206 | void (*phy_prep)(struct cphy *phy, struct adapter *adapter, | ||
207 | int phy_addr, const struct mdio_ops *ops); | ||
208 | unsigned int caps; | ||
209 | const char *desc; | ||
210 | }; | ||
211 | |||
212 | struct mc5_stats { | 203 | struct mc5_stats { |
213 | unsigned long parity_err; | 204 | unsigned long parity_err; |
214 | unsigned long active_rgn_full; | 205 | unsigned long active_rgn_full; |
@@ -358,6 +349,7 @@ struct qset_params { /* SGE queue set parameters */ | |||
358 | unsigned int jumbo_size; /* # of entries in jumbo free list */ | 349 | unsigned int jumbo_size; /* # of entries in jumbo free list */ |
359 | unsigned int txq_size[SGE_TXQ_PER_SET]; /* Tx queue sizes */ | 350 | unsigned int txq_size[SGE_TXQ_PER_SET]; /* Tx queue sizes */ |
360 | unsigned int cong_thres; /* FL congestion threshold */ | 351 | unsigned int cong_thres; /* FL congestion threshold */ |
352 | unsigned int vector; /* Interrupt (line or vector) number */ | ||
361 | }; | 353 | }; |
362 | 354 | ||
363 | struct sge_params { | 355 | struct sge_params { |
@@ -525,12 +517,25 @@ enum { | |||
525 | MAC_RXFIFO_SIZE = 32768 | 517 | MAC_RXFIFO_SIZE = 32768 |
526 | }; | 518 | }; |
527 | 519 | ||
528 | /* IEEE 802.3ae specified MDIO devices */ | 520 | /* IEEE 802.3 specified MDIO devices */ |
529 | enum { | 521 | enum { |
530 | MDIO_DEV_PMA_PMD = 1, | 522 | MDIO_DEV_PMA_PMD = 1, |
531 | MDIO_DEV_WIS = 2, | 523 | MDIO_DEV_WIS = 2, |
532 | MDIO_DEV_PCS = 3, | 524 | MDIO_DEV_PCS = 3, |
533 | MDIO_DEV_XGXS = 4 | 525 | MDIO_DEV_XGXS = 4, |
526 | MDIO_DEV_ANEG = 7, | ||
527 | MDIO_DEV_VEND1 = 30, | ||
528 | MDIO_DEV_VEND2 = 31 | ||
529 | }; | ||
530 | |||
531 | /* LASI control and status registers */ | ||
532 | enum { | ||
533 | RX_ALARM_CTRL = 0x9000, | ||
534 | TX_ALARM_CTRL = 0x9001, | ||
535 | LASI_CTRL = 0x9002, | ||
536 | RX_ALARM_STAT = 0x9003, | ||
537 | TX_ALARM_STAT = 0x9004, | ||
538 | LASI_STAT = 0x9005 | ||
534 | }; | 539 | }; |
535 | 540 | ||
536 | /* PHY loopback direction */ | 541 | /* PHY loopback direction */ |
@@ -542,12 +547,23 @@ enum { | |||
542 | /* PHY interrupt types */ | 547 | /* PHY interrupt types */ |
543 | enum { | 548 | enum { |
544 | cphy_cause_link_change = 1, | 549 | cphy_cause_link_change = 1, |
545 | cphy_cause_fifo_error = 2 | 550 | cphy_cause_fifo_error = 2, |
551 | cphy_cause_module_change = 4, | ||
552 | }; | ||
553 | |||
554 | /* PHY module types */ | ||
555 | enum { | ||
556 | phy_modtype_none, | ||
557 | phy_modtype_sr, | ||
558 | phy_modtype_lr, | ||
559 | phy_modtype_lrm, | ||
560 | phy_modtype_twinax, | ||
561 | phy_modtype_twinax_long, | ||
562 | phy_modtype_unknown | ||
546 | }; | 563 | }; |
547 | 564 | ||
548 | /* PHY operations */ | 565 | /* PHY operations */ |
549 | struct cphy_ops { | 566 | struct cphy_ops { |
550 | void (*destroy)(struct cphy *phy); | ||
551 | int (*reset)(struct cphy *phy, int wait); | 567 | int (*reset)(struct cphy *phy, int wait); |
552 | 568 | ||
553 | int (*intr_enable)(struct cphy *phy); | 569 | int (*intr_enable)(struct cphy *phy); |
@@ -568,8 +584,12 @@ struct cphy_ops { | |||
568 | 584 | ||
569 | /* A PHY instance */ | 585 | /* A PHY instance */ |
570 | struct cphy { | 586 | struct cphy { |
571 | int addr; /* PHY address */ | 587 | u8 addr; /* PHY address */ |
588 | u8 modtype; /* PHY module type */ | ||
589 | short priv; /* scratch pad */ | ||
590 | unsigned int caps; /* PHY capabilities */ | ||
572 | struct adapter *adapter; /* associated adapter */ | 591 | struct adapter *adapter; /* associated adapter */ |
592 | const char *desc; /* PHY description */ | ||
573 | unsigned long fifo_errors; /* FIFO over/under-flows */ | 593 | unsigned long fifo_errors; /* FIFO over/under-flows */ |
574 | const struct cphy_ops *ops; /* PHY operations */ | 594 | const struct cphy_ops *ops; /* PHY operations */ |
575 | int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr, | 595 | int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr, |
@@ -594,10 +614,13 @@ static inline int mdio_write(struct cphy *phy, int mmd, int reg, | |||
594 | /* Convenience initializer */ | 614 | /* Convenience initializer */ |
595 | static inline void cphy_init(struct cphy *phy, struct adapter *adapter, | 615 | static inline void cphy_init(struct cphy *phy, struct adapter *adapter, |
596 | int phy_addr, struct cphy_ops *phy_ops, | 616 | int phy_addr, struct cphy_ops *phy_ops, |
597 | const struct mdio_ops *mdio_ops) | 617 | const struct mdio_ops *mdio_ops, |
618 | unsigned int caps, const char *desc) | ||
598 | { | 619 | { |
599 | phy->adapter = adapter; | ||
600 | phy->addr = phy_addr; | 620 | phy->addr = phy_addr; |
621 | phy->caps = caps; | ||
622 | phy->adapter = adapter; | ||
623 | phy->desc = desc; | ||
601 | phy->ops = phy_ops; | 624 | phy->ops = phy_ops; |
602 | if (mdio_ops) { | 625 | if (mdio_ops) { |
603 | phy->mdio_read = mdio_ops->read; | 626 | phy->mdio_read = mdio_ops->read; |
@@ -668,7 +691,12 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, | |||
668 | unsigned int set); | 691 | unsigned int set); |
669 | int t3_phy_reset(struct cphy *phy, int mmd, int wait); | 692 | int t3_phy_reset(struct cphy *phy, int mmd, int wait); |
670 | int t3_phy_advertise(struct cphy *phy, unsigned int advert); | 693 | int t3_phy_advertise(struct cphy *phy, unsigned int advert); |
694 | int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert); | ||
671 | int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex); | 695 | int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex); |
696 | int t3_phy_lasi_intr_enable(struct cphy *phy); | ||
697 | int t3_phy_lasi_intr_disable(struct cphy *phy); | ||
698 | int t3_phy_lasi_intr_clear(struct cphy *phy); | ||
699 | int t3_phy_lasi_intr_handler(struct cphy *phy); | ||
672 | 700 | ||
673 | void t3_intr_enable(struct adapter *adapter); | 701 | void t3_intr_enable(struct adapter *adapter); |
674 | void t3_intr_disable(struct adapter *adapter); | 702 | void t3_intr_disable(struct adapter *adapter); |
@@ -698,6 +726,7 @@ int t3_check_fw_version(struct adapter *adapter, int *must_load); | |||
698 | int t3_init_hw(struct adapter *adapter, u32 fw_params); | 726 | int t3_init_hw(struct adapter *adapter, u32 fw_params); |
699 | void mac_prep(struct cmac *mac, struct adapter *adapter, int index); | 727 | void mac_prep(struct cmac *mac, struct adapter *adapter, int index); |
700 | void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); | 728 | void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); |
729 | int t3_reset_adapter(struct adapter *adapter); | ||
701 | int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | 730 | int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, |
702 | int reset); | 731 | int reset); |
703 | int t3_replay_prep_adapter(struct adapter *adapter); | 732 | int t3_replay_prep_adapter(struct adapter *adapter); |
@@ -774,14 +803,16 @@ int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]); | |||
774 | int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op, | 803 | int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op, |
775 | unsigned int credits); | 804 | unsigned int credits); |
776 | 805 | ||
777 | void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, | 806 | int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, |
778 | int phy_addr, const struct mdio_ops *mdio_ops); | 807 | int phy_addr, const struct mdio_ops *mdio_ops); |
779 | void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, | 808 | int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, |
780 | int phy_addr, const struct mdio_ops *mdio_ops); | 809 | int phy_addr, const struct mdio_ops *mdio_ops); |
781 | void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, | 810 | int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, |
782 | int phy_addr, const struct mdio_ops *mdio_ops); | 811 | int phy_addr, const struct mdio_ops *mdio_ops); |
783 | void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, | 812 | int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, |
784 | const struct mdio_ops *mdio_ops); | 813 | int phy_addr, const struct mdio_ops *mdio_ops); |
785 | void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, | 814 | int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, |
786 | int phy_addr, const struct mdio_ops *mdio_ops); | 815 | const struct mdio_ops *mdio_ops); |
816 | int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, | ||
817 | int phy_addr, const struct mdio_ops *mdio_ops); | ||
787 | #endif /* __CHELSIO_COMMON_H */ | 818 | #endif /* __CHELSIO_COMMON_H */ |
diff --git a/drivers/net/cxgb3/cxgb3_ctl_defs.h b/drivers/net/cxgb3/cxgb3_ctl_defs.h index 6ad92405d9a0..1d8d46eb3c96 100644 --- a/drivers/net/cxgb3/cxgb3_ctl_defs.h +++ b/drivers/net/cxgb3/cxgb3_ctl_defs.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h index 45e92164c260..47e53769af5b 100644 --- a/drivers/net/cxgb3/cxgb3_defs.h +++ b/drivers/net/cxgb3/cxgb3_defs.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/cxgb3_ioctl.h b/drivers/net/cxgb3/cxgb3_ioctl.h index 68200a14065e..b19e4376ba76 100644 --- a/drivers/net/cxgb3/cxgb3_ioctl.h +++ b/drivers/net/cxgb3/cxgb3_ioctl.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -92,6 +92,8 @@ struct ch_qset_params { | |||
92 | int32_t polling; | 92 | int32_t polling; |
93 | int32_t lro; | 93 | int32_t lro; |
94 | int32_t cong_thres; | 94 | int32_t cong_thres; |
95 | int32_t vector; | ||
96 | int32_t qnum; | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | struct ch_pktsched_params { | 99 | struct ch_pktsched_params { |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 5447f3e60f07..1ace41a13ac3 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -208,6 +208,31 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, | |||
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | /** | ||
212 | * t3_os_phymod_changed - handle PHY module changes | ||
213 | * @phy: the PHY reporting the module change | ||
214 | * @mod_type: new module type | ||
215 | * | ||
216 | * This is the OS-dependent handler for PHY module changes. It is | ||
217 | * invoked when a PHY module is removed or inserted for any OS-specific | ||
218 | * processing. | ||
219 | */ | ||
220 | void t3_os_phymod_changed(struct adapter *adap, int port_id) | ||
221 | { | ||
222 | static const char *mod_str[] = { | ||
223 | NULL, "SR", "LR", "LRM", "TWINAX", "TWINAX", "unknown" | ||
224 | }; | ||
225 | |||
226 | const struct net_device *dev = adap->port[port_id]; | ||
227 | const struct port_info *pi = netdev_priv(dev); | ||
228 | |||
229 | if (pi->phy.modtype == phy_modtype_none) | ||
230 | printk(KERN_INFO "%s: PHY module unplugged\n", dev->name); | ||
231 | else | ||
232 | printk(KERN_INFO "%s: %s PHY module inserted\n", dev->name, | ||
233 | mod_str[pi->phy.modtype]); | ||
234 | } | ||
235 | |||
211 | static void cxgb_set_rxmode(struct net_device *dev) | 236 | static void cxgb_set_rxmode(struct net_device *dev) |
212 | { | 237 | { |
213 | struct t3_rx_mode rm; | 238 | struct t3_rx_mode rm; |
@@ -274,10 +299,10 @@ static void name_msix_vecs(struct adapter *adap) | |||
274 | 299 | ||
275 | for (i = 0; i < pi->nqsets; i++, msi_idx++) { | 300 | for (i = 0; i < pi->nqsets; i++, msi_idx++) { |
276 | snprintf(adap->msix_info[msi_idx].desc, n, | 301 | snprintf(adap->msix_info[msi_idx].desc, n, |
277 | "%s (queue %d)", d->name, i); | 302 | "%s-%d", d->name, pi->first_qset + i); |
278 | adap->msix_info[msi_idx].desc[n] = 0; | 303 | adap->msix_info[msi_idx].desc[n] = 0; |
279 | } | 304 | } |
280 | } | 305 | } |
281 | } | 306 | } |
282 | 307 | ||
283 | static int request_msix_data_irqs(struct adapter *adap) | 308 | static int request_msix_data_irqs(struct adapter *adap) |
@@ -306,6 +331,22 @@ static int request_msix_data_irqs(struct adapter *adap) | |||
306 | return 0; | 331 | return 0; |
307 | } | 332 | } |
308 | 333 | ||
334 | static void free_irq_resources(struct adapter *adapter) | ||
335 | { | ||
336 | if (adapter->flags & USING_MSIX) { | ||
337 | int i, n = 0; | ||
338 | |||
339 | free_irq(adapter->msix_info[0].vec, adapter); | ||
340 | for_each_port(adapter, i) | ||
341 | n += adap2pinfo(adapter, i)->nqsets; | ||
342 | |||
343 | for (i = 0; i < n; ++i) | ||
344 | free_irq(adapter->msix_info[i + 1].vec, | ||
345 | &adapter->sge.qs[i]); | ||
346 | } else | ||
347 | free_irq(adapter->pdev->irq, adapter); | ||
348 | } | ||
349 | |||
309 | static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt, | 350 | static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt, |
310 | unsigned long n) | 351 | unsigned long n) |
311 | { | 352 | { |
@@ -473,12 +514,16 @@ static int setup_sge_qsets(struct adapter *adap) | |||
473 | struct port_info *pi = netdev_priv(dev); | 514 | struct port_info *pi = netdev_priv(dev); |
474 | 515 | ||
475 | pi->qs = &adap->sge.qs[pi->first_qset]; | 516 | pi->qs = &adap->sge.qs[pi->first_qset]; |
476 | for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { | 517 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; |
518 | ++j, ++qset_idx) { | ||
519 | if (!pi->rx_csum_offload) | ||
520 | adap->params.sge.qset[qset_idx].lro = 0; | ||
477 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | 521 | err = t3_sge_alloc_qset(adap, qset_idx, 1, |
478 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | 522 | (adap->flags & USING_MSIX) ? qset_idx + 1 : |
479 | irq_idx, | 523 | irq_idx, |
480 | &adap->params.sge.qset[qset_idx], ntxq, dev); | 524 | &adap->params.sge.qset[qset_idx], ntxq, dev); |
481 | if (err) { | 525 | if (err) { |
526 | t3_stop_sge_timers(adap); | ||
482 | t3_free_sge_resources(adap); | 527 | t3_free_sge_resources(adap); |
483 | return err; | 528 | return err; |
484 | } | 529 | } |
@@ -739,11 +784,12 @@ static void init_port_mtus(struct adapter *adapter) | |||
739 | t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus); | 784 | t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus); |
740 | } | 785 | } |
741 | 786 | ||
742 | static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, | 787 | static int send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, |
743 | int hi, int port) | 788 | int hi, int port) |
744 | { | 789 | { |
745 | struct sk_buff *skb; | 790 | struct sk_buff *skb; |
746 | struct mngt_pktsched_wr *req; | 791 | struct mngt_pktsched_wr *req; |
792 | int ret; | ||
747 | 793 | ||
748 | skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); | 794 | skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); |
749 | req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req)); | 795 | req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req)); |
@@ -754,20 +800,28 @@ static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, | |||
754 | req->min = lo; | 800 | req->min = lo; |
755 | req->max = hi; | 801 | req->max = hi; |
756 | req->binding = port; | 802 | req->binding = port; |
757 | t3_mgmt_tx(adap, skb); | 803 | ret = t3_mgmt_tx(adap, skb); |
804 | |||
805 | return ret; | ||
758 | } | 806 | } |
759 | 807 | ||
760 | static void bind_qsets(struct adapter *adap) | 808 | static int bind_qsets(struct adapter *adap) |
761 | { | 809 | { |
762 | int i, j; | 810 | int i, j, err = 0; |
763 | 811 | ||
764 | for_each_port(adap, i) { | 812 | for_each_port(adap, i) { |
765 | const struct port_info *pi = adap2pinfo(adap, i); | 813 | const struct port_info *pi = adap2pinfo(adap, i); |
766 | 814 | ||
767 | for (j = 0; j < pi->nqsets; ++j) | 815 | for (j = 0; j < pi->nqsets; ++j) { |
768 | send_pktsched_cmd(adap, 1, pi->first_qset + j, -1, | 816 | int ret = send_pktsched_cmd(adap, 1, |
769 | -1, i); | 817 | pi->first_qset + j, -1, |
818 | -1, i); | ||
819 | if (ret) | ||
820 | err = ret; | ||
821 | } | ||
770 | } | 822 | } |
823 | |||
824 | return err; | ||
771 | } | 825 | } |
772 | 826 | ||
773 | #define FW_FNAME "t3fw-%d.%d.%d.bin" | 827 | #define FW_FNAME "t3fw-%d.%d.%d.bin" |
@@ -891,6 +945,13 @@ static int cxgb_up(struct adapter *adap) | |||
891 | goto out; | 945 | goto out; |
892 | } | 946 | } |
893 | 947 | ||
948 | /* | ||
949 | * Clear interrupts now to catch errors if t3_init_hw fails. | ||
950 | * We clear them again later as initialization may trigger | ||
951 | * conditions that can interrupt. | ||
952 | */ | ||
953 | t3_intr_clear(adap); | ||
954 | |||
894 | err = t3_init_hw(adap, 0); | 955 | err = t3_init_hw(adap, 0); |
895 | if (err) | 956 | if (err) |
896 | goto out; | 957 | goto out; |
@@ -946,9 +1007,16 @@ static int cxgb_up(struct adapter *adap) | |||
946 | t3_write_reg(adap, A_TP_INT_ENABLE, 0x7fbfffff); | 1007 | t3_write_reg(adap, A_TP_INT_ENABLE, 0x7fbfffff); |
947 | } | 1008 | } |
948 | 1009 | ||
949 | if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX) | 1010 | if (!(adap->flags & QUEUES_BOUND)) { |
950 | bind_qsets(adap); | 1011 | err = bind_qsets(adap); |
951 | adap->flags |= QUEUES_BOUND; | 1012 | if (err) { |
1013 | CH_ERR(adap, "failed to bind qsets, err %d\n", err); | ||
1014 | t3_intr_disable(adap); | ||
1015 | free_irq_resources(adap); | ||
1016 | goto out; | ||
1017 | } | ||
1018 | adap->flags |= QUEUES_BOUND; | ||
1019 | } | ||
952 | 1020 | ||
953 | out: | 1021 | out: |
954 | return err; | 1022 | return err; |
@@ -967,19 +1035,7 @@ static void cxgb_down(struct adapter *adapter) | |||
967 | t3_intr_disable(adapter); | 1035 | t3_intr_disable(adapter); |
968 | spin_unlock_irq(&adapter->work_lock); | 1036 | spin_unlock_irq(&adapter->work_lock); |
969 | 1037 | ||
970 | if (adapter->flags & USING_MSIX) { | 1038 | free_irq_resources(adapter); |
971 | int i, n = 0; | ||
972 | |||
973 | free_irq(adapter->msix_info[0].vec, adapter); | ||
974 | for_each_port(adapter, i) | ||
975 | n += adap2pinfo(adapter, i)->nqsets; | ||
976 | |||
977 | for (i = 0; i < n; ++i) | ||
978 | free_irq(adapter->msix_info[i + 1].vec, | ||
979 | &adapter->sge.qs[i]); | ||
980 | } else | ||
981 | free_irq(adapter->pdev->irq, adapter); | ||
982 | |||
983 | flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ | 1039 | flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ |
984 | quiesce_rx(adapter); | 1040 | quiesce_rx(adapter); |
985 | } | 1041 | } |
@@ -1100,9 +1156,9 @@ static int cxgb_close(struct net_device *dev) | |||
1100 | netif_carrier_off(dev); | 1156 | netif_carrier_off(dev); |
1101 | t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); | 1157 | t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); |
1102 | 1158 | ||
1103 | spin_lock(&adapter->work_lock); /* sync with update task */ | 1159 | spin_lock_irq(&adapter->work_lock); /* sync with update task */ |
1104 | clear_bit(pi->port_id, &adapter->open_device_map); | 1160 | clear_bit(pi->port_id, &adapter->open_device_map); |
1105 | spin_unlock(&adapter->work_lock); | 1161 | spin_unlock_irq(&adapter->work_lock); |
1106 | 1162 | ||
1107 | if (!(adapter->open_device_map & PORT_MASK)) | 1163 | if (!(adapter->open_device_map & PORT_MASK)) |
1108 | cancel_rearming_delayed_workqueue(cxgb3_wq, | 1164 | cancel_rearming_delayed_workqueue(cxgb3_wq, |
@@ -1284,8 +1340,8 @@ static unsigned long collect_sge_port_stats(struct adapter *adapter, | |||
1284 | int i; | 1340 | int i; |
1285 | unsigned long tot = 0; | 1341 | unsigned long tot = 0; |
1286 | 1342 | ||
1287 | for (i = 0; i < p->nqsets; ++i) | 1343 | for (i = p->first_qset; i < p->first_qset + p->nqsets; ++i) |
1288 | tot += adapter->sge.qs[i + p->first_qset].port_stats[idx]; | 1344 | tot += adapter->sge.qs[i].port_stats[idx]; |
1289 | return tot; | 1345 | return tot; |
1290 | } | 1346 | } |
1291 | 1347 | ||
@@ -1485,11 +1541,22 @@ static int speed_duplex_to_caps(int speed, int duplex) | |||
1485 | 1541 | ||
1486 | static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1542 | static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1487 | { | 1543 | { |
1544 | int cap; | ||
1488 | struct port_info *p = netdev_priv(dev); | 1545 | struct port_info *p = netdev_priv(dev); |
1489 | struct link_config *lc = &p->link_config; | 1546 | struct link_config *lc = &p->link_config; |
1490 | 1547 | ||
1491 | if (!(lc->supported & SUPPORTED_Autoneg)) | 1548 | if (!(lc->supported & SUPPORTED_Autoneg)) { |
1492 | return -EOPNOTSUPP; /* can't change speed/duplex */ | 1549 | /* |
1550 | * PHY offers a single speed/duplex. See if that's what's | ||
1551 | * being requested. | ||
1552 | */ | ||
1553 | if (cmd->autoneg == AUTONEG_DISABLE) { | ||
1554 | cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); | ||
1555 | if (lc->supported & cap) | ||
1556 | return 0; | ||
1557 | } | ||
1558 | return -EINVAL; | ||
1559 | } | ||
1493 | 1560 | ||
1494 | if (cmd->autoneg == AUTONEG_DISABLE) { | 1561 | if (cmd->autoneg == AUTONEG_DISABLE) { |
1495 | int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); | 1562 | int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); |
@@ -1568,8 +1635,10 @@ static int set_rx_csum(struct net_device *dev, u32 data) | |||
1568 | struct adapter *adap = p->adapter; | 1635 | struct adapter *adap = p->adapter; |
1569 | int i; | 1636 | int i; |
1570 | 1637 | ||
1571 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) | 1638 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) { |
1639 | adap->params.sge.qset[i].lro = 0; | ||
1572 | adap->sge.qs[i].lro_enabled = 0; | 1640 | adap->sge.qs[i].lro_enabled = 0; |
1641 | } | ||
1573 | } | 1642 | } |
1574 | return 0; | 1643 | return 0; |
1575 | } | 1644 | } |
@@ -1775,6 +1844,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1775 | int i; | 1844 | int i; |
1776 | struct qset_params *q; | 1845 | struct qset_params *q; |
1777 | struct ch_qset_params t; | 1846 | struct ch_qset_params t; |
1847 | int q1 = pi->first_qset; | ||
1848 | int nqsets = pi->nqsets; | ||
1778 | 1849 | ||
1779 | if (!capable(CAP_NET_ADMIN)) | 1850 | if (!capable(CAP_NET_ADMIN)) |
1780 | return -EPERM; | 1851 | return -EPERM; |
@@ -1797,6 +1868,16 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1797 | || !in_range(t.rspq_size, MIN_RSPQ_ENTRIES, | 1868 | || !in_range(t.rspq_size, MIN_RSPQ_ENTRIES, |
1798 | MAX_RSPQ_ENTRIES)) | 1869 | MAX_RSPQ_ENTRIES)) |
1799 | return -EINVAL; | 1870 | return -EINVAL; |
1871 | |||
1872 | if ((adapter->flags & FULL_INIT_DONE) && t.lro > 0) | ||
1873 | for_each_port(adapter, i) { | ||
1874 | pi = adap2pinfo(adapter, i); | ||
1875 | if (t.qset_idx >= pi->first_qset && | ||
1876 | t.qset_idx < pi->first_qset + pi->nqsets && | ||
1877 | !pi->rx_csum_offload) | ||
1878 | return -EINVAL; | ||
1879 | } | ||
1880 | |||
1800 | if ((adapter->flags & FULL_INIT_DONE) && | 1881 | if ((adapter->flags & FULL_INIT_DONE) && |
1801 | (t.rspq_size >= 0 || t.fl_size[0] >= 0 || | 1882 | (t.rspq_size >= 0 || t.fl_size[0] >= 0 || |
1802 | t.fl_size[1] >= 0 || t.txq_size[0] >= 0 || | 1883 | t.fl_size[1] >= 0 || t.txq_size[0] >= 0 || |
@@ -1804,6 +1885,20 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1804 | t.polling >= 0 || t.cong_thres >= 0)) | 1885 | t.polling >= 0 || t.cong_thres >= 0)) |
1805 | return -EBUSY; | 1886 | return -EBUSY; |
1806 | 1887 | ||
1888 | /* Allow setting of any available qset when offload enabled */ | ||
1889 | if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) { | ||
1890 | q1 = 0; | ||
1891 | for_each_port(adapter, i) { | ||
1892 | pi = adap2pinfo(adapter, i); | ||
1893 | nqsets += pi->first_qset + pi->nqsets; | ||
1894 | } | ||
1895 | } | ||
1896 | |||
1897 | if (t.qset_idx < q1) | ||
1898 | return -EINVAL; | ||
1899 | if (t.qset_idx > q1 + nqsets - 1) | ||
1900 | return -EINVAL; | ||
1901 | |||
1807 | q = &adapter->params.sge.qset[t.qset_idx]; | 1902 | q = &adapter->params.sge.qset[t.qset_idx]; |
1808 | 1903 | ||
1809 | if (t.rspq_size >= 0) | 1904 | if (t.rspq_size >= 0) |
@@ -1853,13 +1948,26 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1853 | case CHELSIO_GET_QSET_PARAMS:{ | 1948 | case CHELSIO_GET_QSET_PARAMS:{ |
1854 | struct qset_params *q; | 1949 | struct qset_params *q; |
1855 | struct ch_qset_params t; | 1950 | struct ch_qset_params t; |
1951 | int q1 = pi->first_qset; | ||
1952 | int nqsets = pi->nqsets; | ||
1953 | int i; | ||
1856 | 1954 | ||
1857 | if (copy_from_user(&t, useraddr, sizeof(t))) | 1955 | if (copy_from_user(&t, useraddr, sizeof(t))) |
1858 | return -EFAULT; | 1956 | return -EFAULT; |
1859 | if (t.qset_idx >= SGE_QSETS) | 1957 | |
1958 | /* Display qsets for all ports when offload enabled */ | ||
1959 | if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) { | ||
1960 | q1 = 0; | ||
1961 | for_each_port(adapter, i) { | ||
1962 | pi = adap2pinfo(adapter, i); | ||
1963 | nqsets = pi->first_qset + pi->nqsets; | ||
1964 | } | ||
1965 | } | ||
1966 | |||
1967 | if (t.qset_idx >= nqsets) | ||
1860 | return -EINVAL; | 1968 | return -EINVAL; |
1861 | 1969 | ||
1862 | q = &adapter->params.sge.qset[t.qset_idx]; | 1970 | q = &adapter->params.sge.qset[q1 + t.qset_idx]; |
1863 | t.rspq_size = q->rspq_size; | 1971 | t.rspq_size = q->rspq_size; |
1864 | t.txq_size[0] = q->txq_size[0]; | 1972 | t.txq_size[0] = q->txq_size[0]; |
1865 | t.txq_size[1] = q->txq_size[1]; | 1973 | t.txq_size[1] = q->txq_size[1]; |
@@ -1870,6 +1978,12 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1870 | t.lro = q->lro; | 1978 | t.lro = q->lro; |
1871 | t.intr_lat = q->coalesce_usecs; | 1979 | t.intr_lat = q->coalesce_usecs; |
1872 | t.cong_thres = q->cong_thres; | 1980 | t.cong_thres = q->cong_thres; |
1981 | t.qnum = q1; | ||
1982 | |||
1983 | if (adapter->flags & USING_MSIX) | ||
1984 | t.vector = adapter->msix_info[q1 + t.qset_idx + 1].vec; | ||
1985 | else | ||
1986 | t.vector = adapter->pdev->irq; | ||
1873 | 1987 | ||
1874 | if (copy_to_user(useraddr, &t, sizeof(t))) | 1988 | if (copy_to_user(useraddr, &t, sizeof(t))) |
1875 | return -EFAULT; | 1989 | return -EFAULT; |
@@ -2117,7 +2231,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | |||
2117 | mmd = data->phy_id >> 8; | 2231 | mmd = data->phy_id >> 8; |
2118 | if (!mmd) | 2232 | if (!mmd) |
2119 | mmd = MDIO_DEV_PCS; | 2233 | mmd = MDIO_DEV_PCS; |
2120 | else if (mmd > MDIO_DEV_XGXS) | 2234 | else if (mmd > MDIO_DEV_VEND2) |
2121 | return -EINVAL; | 2235 | return -EINVAL; |
2122 | 2236 | ||
2123 | ret = | 2237 | ret = |
@@ -2143,7 +2257,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | |||
2143 | mmd = data->phy_id >> 8; | 2257 | mmd = data->phy_id >> 8; |
2144 | if (!mmd) | 2258 | if (!mmd) |
2145 | mmd = MDIO_DEV_PCS; | 2259 | mmd = MDIO_DEV_PCS; |
2146 | else if (mmd > MDIO_DEV_XGXS) | 2260 | else if (mmd > MDIO_DEV_VEND2) |
2147 | return -EINVAL; | 2261 | return -EINVAL; |
2148 | 2262 | ||
2149 | ret = | 2263 | ret = |
@@ -2215,8 +2329,8 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p) | |||
2215 | { | 2329 | { |
2216 | int i; | 2330 | int i; |
2217 | 2331 | ||
2218 | for (i = 0; i < p->nqsets; i++) { | 2332 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) { |
2219 | struct sge_rspq *q = &adap->sge.qs[i + p->first_qset].rspq; | 2333 | struct sge_rspq *q = &adap->sge.qs[i].rspq; |
2220 | 2334 | ||
2221 | spin_lock_irq(&q->lock); | 2335 | spin_lock_irq(&q->lock); |
2222 | spin_unlock_irq(&q->lock); | 2336 | spin_unlock_irq(&q->lock); |
@@ -2290,7 +2404,7 @@ static void check_link_status(struct adapter *adapter) | |||
2290 | struct net_device *dev = adapter->port[i]; | 2404 | struct net_device *dev = adapter->port[i]; |
2291 | struct port_info *p = netdev_priv(dev); | 2405 | struct port_info *p = netdev_priv(dev); |
2292 | 2406 | ||
2293 | if (!(p->port_type->caps & SUPPORTED_IRQ) && netif_running(dev)) | 2407 | if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) |
2294 | t3_link_changed(adapter, i); | 2408 | t3_link_changed(adapter, i); |
2295 | } | 2409 | } |
2296 | } | 2410 | } |
@@ -2355,10 +2469,10 @@ static void t3_adap_check_task(struct work_struct *work) | |||
2355 | check_t3b2_mac(adapter); | 2469 | check_t3b2_mac(adapter); |
2356 | 2470 | ||
2357 | /* Schedule the next check update if any port is active. */ | 2471 | /* Schedule the next check update if any port is active. */ |
2358 | spin_lock(&adapter->work_lock); | 2472 | spin_lock_irq(&adapter->work_lock); |
2359 | if (adapter->open_device_map & PORT_MASK) | 2473 | if (adapter->open_device_map & PORT_MASK) |
2360 | schedule_chk_task(adapter); | 2474 | schedule_chk_task(adapter); |
2361 | spin_unlock(&adapter->work_lock); | 2475 | spin_unlock_irq(&adapter->work_lock); |
2362 | } | 2476 | } |
2363 | 2477 | ||
2364 | /* | 2478 | /* |
@@ -2403,6 +2517,96 @@ void t3_os_ext_intr_handler(struct adapter *adapter) | |||
2403 | spin_unlock(&adapter->work_lock); | 2517 | spin_unlock(&adapter->work_lock); |
2404 | } | 2518 | } |
2405 | 2519 | ||
2520 | static int t3_adapter_error(struct adapter *adapter, int reset) | ||
2521 | { | ||
2522 | int i, ret = 0; | ||
2523 | |||
2524 | /* Stop all ports */ | ||
2525 | for_each_port(adapter, i) { | ||
2526 | struct net_device *netdev = adapter->port[i]; | ||
2527 | |||
2528 | if (netif_running(netdev)) | ||
2529 | cxgb_close(netdev); | ||
2530 | } | ||
2531 | |||
2532 | if (is_offload(adapter) && | ||
2533 | test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) | ||
2534 | offload_close(&adapter->tdev); | ||
2535 | |||
2536 | /* Stop SGE timers */ | ||
2537 | t3_stop_sge_timers(adapter); | ||
2538 | |||
2539 | adapter->flags &= ~FULL_INIT_DONE; | ||
2540 | |||
2541 | if (reset) | ||
2542 | ret = t3_reset_adapter(adapter); | ||
2543 | |||
2544 | pci_disable_device(adapter->pdev); | ||
2545 | |||
2546 | return ret; | ||
2547 | } | ||
2548 | |||
2549 | static int t3_reenable_adapter(struct adapter *adapter) | ||
2550 | { | ||
2551 | if (pci_enable_device(adapter->pdev)) { | ||
2552 | dev_err(&adapter->pdev->dev, | ||
2553 | "Cannot re-enable PCI device after reset.\n"); | ||
2554 | goto err; | ||
2555 | } | ||
2556 | pci_set_master(adapter->pdev); | ||
2557 | pci_restore_state(adapter->pdev); | ||
2558 | |||
2559 | /* Free sge resources */ | ||
2560 | t3_free_sge_resources(adapter); | ||
2561 | |||
2562 | if (t3_replay_prep_adapter(adapter)) | ||
2563 | goto err; | ||
2564 | |||
2565 | return 0; | ||
2566 | err: | ||
2567 | return -1; | ||
2568 | } | ||
2569 | |||
2570 | static void t3_resume_ports(struct adapter *adapter) | ||
2571 | { | ||
2572 | int i; | ||
2573 | |||
2574 | /* Restart the ports */ | ||
2575 | for_each_port(adapter, i) { | ||
2576 | struct net_device *netdev = adapter->port[i]; | ||
2577 | |||
2578 | if (netif_running(netdev)) { | ||
2579 | if (cxgb_open(netdev)) { | ||
2580 | dev_err(&adapter->pdev->dev, | ||
2581 | "can't bring device back up" | ||
2582 | " after reset\n"); | ||
2583 | continue; | ||
2584 | } | ||
2585 | } | ||
2586 | } | ||
2587 | } | ||
2588 | |||
2589 | /* | ||
2590 | * processes a fatal error. | ||
2591 | * Bring the ports down, reset the chip, bring the ports back up. | ||
2592 | */ | ||
2593 | static void fatal_error_task(struct work_struct *work) | ||
2594 | { | ||
2595 | struct adapter *adapter = container_of(work, struct adapter, | ||
2596 | fatal_error_handler_task); | ||
2597 | int err = 0; | ||
2598 | |||
2599 | rtnl_lock(); | ||
2600 | err = t3_adapter_error(adapter, 1); | ||
2601 | if (!err) | ||
2602 | err = t3_reenable_adapter(adapter); | ||
2603 | if (!err) | ||
2604 | t3_resume_ports(adapter); | ||
2605 | |||
2606 | CH_ALERT(adapter, "adapter reset %s\n", err ? "failed" : "succeeded"); | ||
2607 | rtnl_unlock(); | ||
2608 | } | ||
2609 | |||
2406 | void t3_fatal_err(struct adapter *adapter) | 2610 | void t3_fatal_err(struct adapter *adapter) |
2407 | { | 2611 | { |
2408 | unsigned int fw_status[4]; | 2612 | unsigned int fw_status[4]; |
@@ -2413,7 +2617,11 @@ void t3_fatal_err(struct adapter *adapter) | |||
2413 | t3_write_reg(adapter, A_XGM_RX_CTRL, 0); | 2617 | t3_write_reg(adapter, A_XGM_RX_CTRL, 0); |
2414 | t3_write_reg(adapter, XGM_REG(A_XGM_TX_CTRL, 1), 0); | 2618 | t3_write_reg(adapter, XGM_REG(A_XGM_TX_CTRL, 1), 0); |
2415 | t3_write_reg(adapter, XGM_REG(A_XGM_RX_CTRL, 1), 0); | 2619 | t3_write_reg(adapter, XGM_REG(A_XGM_RX_CTRL, 1), 0); |
2620 | |||
2621 | spin_lock(&adapter->work_lock); | ||
2416 | t3_intr_disable(adapter); | 2622 | t3_intr_disable(adapter); |
2623 | queue_work(cxgb3_wq, &adapter->fatal_error_handler_task); | ||
2624 | spin_unlock(&adapter->work_lock); | ||
2417 | } | 2625 | } |
2418 | CH_ALERT(adapter, "encountered fatal error, operation suspended\n"); | 2626 | CH_ALERT(adapter, "encountered fatal error, operation suspended\n"); |
2419 | if (!t3_cim_ctl_blk_read(adapter, 0xa0, 4, fw_status)) | 2627 | if (!t3_cim_ctl_blk_read(adapter, 0xa0, 4, fw_status)) |
@@ -2435,23 +2643,9 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, | |||
2435 | pci_channel_state_t state) | 2643 | pci_channel_state_t state) |
2436 | { | 2644 | { |
2437 | struct adapter *adapter = pci_get_drvdata(pdev); | 2645 | struct adapter *adapter = pci_get_drvdata(pdev); |
2438 | int i; | 2646 | int ret; |
2439 | |||
2440 | /* Stop all ports */ | ||
2441 | for_each_port(adapter, i) { | ||
2442 | struct net_device *netdev = adapter->port[i]; | ||
2443 | |||
2444 | if (netif_running(netdev)) | ||
2445 | cxgb_close(netdev); | ||
2446 | } | ||
2447 | |||
2448 | if (is_offload(adapter) && | ||
2449 | test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) | ||
2450 | offload_close(&adapter->tdev); | ||
2451 | |||
2452 | adapter->flags &= ~FULL_INIT_DONE; | ||
2453 | 2647 | ||
2454 | pci_disable_device(pdev); | 2648 | ret = t3_adapter_error(adapter, 0); |
2455 | 2649 | ||
2456 | /* Request a slot reset. */ | 2650 | /* Request a slot reset. */ |
2457 | return PCI_ERS_RESULT_NEED_RESET; | 2651 | return PCI_ERS_RESULT_NEED_RESET; |
@@ -2467,22 +2661,9 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev) | |||
2467 | { | 2661 | { |
2468 | struct adapter *adapter = pci_get_drvdata(pdev); | 2662 | struct adapter *adapter = pci_get_drvdata(pdev); |
2469 | 2663 | ||
2470 | if (pci_enable_device(pdev)) { | 2664 | if (!t3_reenable_adapter(adapter)) |
2471 | dev_err(&pdev->dev, | 2665 | return PCI_ERS_RESULT_RECOVERED; |
2472 | "Cannot re-enable PCI device after reset.\n"); | ||
2473 | goto err; | ||
2474 | } | ||
2475 | pci_set_master(pdev); | ||
2476 | pci_restore_state(pdev); | ||
2477 | |||
2478 | /* Free sge resources */ | ||
2479 | t3_free_sge_resources(adapter); | ||
2480 | |||
2481 | if (t3_replay_prep_adapter(adapter)) | ||
2482 | goto err; | ||
2483 | 2666 | ||
2484 | return PCI_ERS_RESULT_RECOVERED; | ||
2485 | err: | ||
2486 | return PCI_ERS_RESULT_DISCONNECT; | 2667 | return PCI_ERS_RESULT_DISCONNECT; |
2487 | } | 2668 | } |
2488 | 2669 | ||
@@ -2496,22 +2677,8 @@ err: | |||
2496 | static void t3_io_resume(struct pci_dev *pdev) | 2677 | static void t3_io_resume(struct pci_dev *pdev) |
2497 | { | 2678 | { |
2498 | struct adapter *adapter = pci_get_drvdata(pdev); | 2679 | struct adapter *adapter = pci_get_drvdata(pdev); |
2499 | int i; | ||
2500 | 2680 | ||
2501 | /* Restart the ports */ | 2681 | t3_resume_ports(adapter); |
2502 | for_each_port(adapter, i) { | ||
2503 | struct net_device *netdev = adapter->port[i]; | ||
2504 | |||
2505 | if (netif_running(netdev)) { | ||
2506 | if (cxgb_open(netdev)) { | ||
2507 | dev_err(&pdev->dev, | ||
2508 | "can't bring device back up" | ||
2509 | " after reset\n"); | ||
2510 | continue; | ||
2511 | } | ||
2512 | netif_device_attach(netdev); | ||
2513 | } | ||
2514 | } | ||
2515 | } | 2682 | } |
2516 | 2683 | ||
2517 | static struct pci_error_handlers t3_err_handler = { | 2684 | static struct pci_error_handlers t3_err_handler = { |
@@ -2520,6 +2687,42 @@ static struct pci_error_handlers t3_err_handler = { | |||
2520 | .resume = t3_io_resume, | 2687 | .resume = t3_io_resume, |
2521 | }; | 2688 | }; |
2522 | 2689 | ||
2690 | /* | ||
2691 | * Set the number of qsets based on the number of CPUs and the number of ports, | ||
2692 | * not to exceed the number of available qsets, assuming there are enough qsets | ||
2693 | * per port in HW. | ||
2694 | */ | ||
2695 | static void set_nqsets(struct adapter *adap) | ||
2696 | { | ||
2697 | int i, j = 0; | ||
2698 | int num_cpus = num_online_cpus(); | ||
2699 | int hwports = adap->params.nports; | ||
2700 | int nqsets = SGE_QSETS; | ||
2701 | |||
2702 | if (adap->params.rev > 0) { | ||
2703 | if (hwports == 2 && | ||
2704 | (hwports * nqsets > SGE_QSETS || | ||
2705 | num_cpus >= nqsets / hwports)) | ||
2706 | nqsets /= hwports; | ||
2707 | if (nqsets > num_cpus) | ||
2708 | nqsets = num_cpus; | ||
2709 | if (nqsets < 1 || hwports == 4) | ||
2710 | nqsets = 1; | ||
2711 | } else | ||
2712 | nqsets = 1; | ||
2713 | |||
2714 | for_each_port(adap, i) { | ||
2715 | struct port_info *pi = adap2pinfo(adap, i); | ||
2716 | |||
2717 | pi->first_qset = j; | ||
2718 | pi->nqsets = nqsets; | ||
2719 | j = pi->first_qset + nqsets; | ||
2720 | |||
2721 | dev_info(&adap->pdev->dev, | ||
2722 | "Port %d using %d queue sets.\n", i, nqsets); | ||
2723 | } | ||
2724 | } | ||
2725 | |||
2523 | static int __devinit cxgb_enable_msix(struct adapter *adap) | 2726 | static int __devinit cxgb_enable_msix(struct adapter *adap) |
2524 | { | 2727 | { |
2525 | struct msix_entry entries[SGE_QSETS + 1]; | 2728 | struct msix_entry entries[SGE_QSETS + 1]; |
@@ -2564,7 +2767,7 @@ static void __devinit print_port_info(struct adapter *adap, | |||
2564 | if (!test_bit(i, &adap->registered_device_map)) | 2767 | if (!test_bit(i, &adap->registered_device_map)) |
2565 | continue; | 2768 | continue; |
2566 | printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n", | 2769 | printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n", |
2567 | dev->name, ai->desc, pi->port_type->desc, | 2770 | dev->name, ai->desc, pi->phy.desc, |
2568 | is_offload(adap) ? "R" : "", adap->params.rev, buf, | 2771 | is_offload(adap) ? "R" : "", adap->params.rev, buf, |
2569 | (adap->flags & USING_MSIX) ? " MSI-X" : | 2772 | (adap->flags & USING_MSIX) ? " MSI-X" : |
2570 | (adap->flags & USING_MSI) ? " MSI" : ""); | 2773 | (adap->flags & USING_MSI) ? " MSI" : ""); |
@@ -2660,6 +2863,7 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2660 | 2863 | ||
2661 | INIT_LIST_HEAD(&adapter->adapter_list); | 2864 | INIT_LIST_HEAD(&adapter->adapter_list); |
2662 | INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); | 2865 | INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); |
2866 | INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task); | ||
2663 | INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); | 2867 | INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); |
2664 | 2868 | ||
2665 | for (i = 0; i < ai->nports; ++i) { | 2869 | for (i = 0; i < ai->nports; ++i) { |
@@ -2677,9 +2881,6 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2677 | pi = netdev_priv(netdev); | 2881 | pi = netdev_priv(netdev); |
2678 | pi->adapter = adapter; | 2882 | pi->adapter = adapter; |
2679 | pi->rx_csum_offload = 1; | 2883 | pi->rx_csum_offload = 1; |
2680 | pi->nqsets = 1; | ||
2681 | pi->first_qset = i; | ||
2682 | pi->activity = 0; | ||
2683 | pi->port_id = i; | 2884 | pi->port_id = i; |
2684 | netif_carrier_off(netdev); | 2885 | netif_carrier_off(netdev); |
2685 | netdev->irq = pdev->irq; | 2886 | netdev->irq = pdev->irq; |
@@ -2756,6 +2957,8 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2756 | else if (msi > 0 && pci_enable_msi(pdev) == 0) | 2957 | else if (msi > 0 && pci_enable_msi(pdev) == 0) |
2757 | adapter->flags |= USING_MSI; | 2958 | adapter->flags |= USING_MSI; |
2758 | 2959 | ||
2960 | set_nqsets(adapter); | ||
2961 | |||
2759 | err = sysfs_create_group(&adapter->port[0]->dev.kobj, | 2962 | err = sysfs_create_group(&adapter->port[0]->dev.kobj, |
2760 | &cxgb3_attr_group); | 2963 | &cxgb3_attr_group); |
2761 | 2964 | ||
@@ -2801,6 +3004,7 @@ static void __devexit remove_one(struct pci_dev *pdev) | |||
2801 | if (test_bit(i, &adapter->registered_device_map)) | 3004 | if (test_bit(i, &adapter->registered_device_map)) |
2802 | unregister_netdev(adapter->port[i]); | 3005 | unregister_netdev(adapter->port[i]); |
2803 | 3006 | ||
3007 | t3_stop_sge_timers(adapter); | ||
2804 | t3_free_sge_resources(adapter); | 3008 | t3_free_sge_resources(adapter); |
2805 | cxgb_disable_msi(adapter); | 3009 | cxgb_disable_msi(adapter); |
2806 | 3010 | ||
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index c5b3de1bb456..265aa8a15afa 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -1018,7 +1018,7 @@ static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e) | |||
1018 | 1018 | ||
1019 | skb = alloc_skb(sizeof(*req), GFP_ATOMIC); | 1019 | skb = alloc_skb(sizeof(*req), GFP_ATOMIC); |
1020 | if (!skb) { | 1020 | if (!skb) { |
1021 | printk(KERN_ERR "%s: cannot allocate skb!\n", __FUNCTION__); | 1021 | printk(KERN_ERR "%s: cannot allocate skb!\n", __func__); |
1022 | return; | 1022 | return; |
1023 | } | 1023 | } |
1024 | skb->priority = CPL_PRIORITY_CONTROL; | 1024 | skb->priority = CPL_PRIORITY_CONTROL; |
@@ -1049,14 +1049,14 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) | |||
1049 | return; | 1049 | return; |
1050 | if (!is_offloading(newdev)) { | 1050 | if (!is_offloading(newdev)) { |
1051 | printk(KERN_WARNING "%s: Redirect to non-offload " | 1051 | printk(KERN_WARNING "%s: Redirect to non-offload " |
1052 | "device ignored.\n", __FUNCTION__); | 1052 | "device ignored.\n", __func__); |
1053 | return; | 1053 | return; |
1054 | } | 1054 | } |
1055 | tdev = dev2t3cdev(olddev); | 1055 | tdev = dev2t3cdev(olddev); |
1056 | BUG_ON(!tdev); | 1056 | BUG_ON(!tdev); |
1057 | if (tdev != dev2t3cdev(newdev)) { | 1057 | if (tdev != dev2t3cdev(newdev)) { |
1058 | printk(KERN_WARNING "%s: Redirect to different " | 1058 | printk(KERN_WARNING "%s: Redirect to different " |
1059 | "offload device ignored.\n", __FUNCTION__); | 1059 | "offload device ignored.\n", __func__); |
1060 | return; | 1060 | return; |
1061 | } | 1061 | } |
1062 | 1062 | ||
@@ -1064,7 +1064,7 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) | |||
1064 | e = t3_l2t_get(tdev, new->neighbour, newdev); | 1064 | e = t3_l2t_get(tdev, new->neighbour, newdev); |
1065 | if (!e) { | 1065 | if (!e) { |
1066 | printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n", | 1066 | printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n", |
1067 | __FUNCTION__); | 1067 | __func__); |
1068 | return; | 1068 | return; |
1069 | } | 1069 | } |
1070 | 1070 | ||
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h index 7a379138b5a6..d514e5019dfc 100644 --- a/drivers/net/cxgb3/cxgb3_offload.h +++ b/drivers/net/cxgb3/cxgb3_offload.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/firmware_exports.h b/drivers/net/cxgb3/firmware_exports.h index b75ddd8777fe..0d9b0e6dccff 100644 --- a/drivers/net/cxgb3/firmware_exports.h +++ b/drivers/net/cxgb3/firmware_exports.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c index 825e510bd9ed..4407ac9bb555 100644 --- a/drivers/net/cxgb3/l2t.c +++ b/drivers/net/cxgb3/l2t.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -86,6 +86,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, | |||
86 | struct l2t_entry *e) | 86 | struct l2t_entry *e) |
87 | { | 87 | { |
88 | struct cpl_l2t_write_req *req; | 88 | struct cpl_l2t_write_req *req; |
89 | struct sk_buff *tmp; | ||
89 | 90 | ||
90 | if (!skb) { | 91 | if (!skb) { |
91 | skb = alloc_skb(sizeof(*req), GFP_ATOMIC); | 92 | skb = alloc_skb(sizeof(*req), GFP_ATOMIC); |
@@ -103,13 +104,11 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, | |||
103 | memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); | 104 | memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); |
104 | skb->priority = CPL_PRIORITY_CONTROL; | 105 | skb->priority = CPL_PRIORITY_CONTROL; |
105 | cxgb3_ofld_send(dev, skb); | 106 | cxgb3_ofld_send(dev, skb); |
106 | while (e->arpq_head) { | 107 | |
107 | skb = e->arpq_head; | 108 | skb_queue_walk_safe(&e->arpq, skb, tmp) { |
108 | e->arpq_head = skb->next; | 109 | __skb_unlink(skb, &e->arpq); |
109 | skb->next = NULL; | ||
110 | cxgb3_ofld_send(dev, skb); | 110 | cxgb3_ofld_send(dev, skb); |
111 | } | 111 | } |
112 | e->arpq_tail = NULL; | ||
113 | e->state = L2T_STATE_VALID; | 112 | e->state = L2T_STATE_VALID; |
114 | 113 | ||
115 | return 0; | 114 | return 0; |
@@ -121,12 +120,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, | |||
121 | */ | 120 | */ |
122 | static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) | 121 | static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) |
123 | { | 122 | { |
124 | skb->next = NULL; | 123 | __skb_queue_tail(&e->arpq, skb); |
125 | if (e->arpq_head) | ||
126 | e->arpq_tail->next = skb; | ||
127 | else | ||
128 | e->arpq_head = skb; | ||
129 | e->arpq_tail = skb; | ||
130 | } | 124 | } |
131 | 125 | ||
132 | int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, | 126 | int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, |
@@ -167,7 +161,7 @@ again: | |||
167 | break; | 161 | break; |
168 | 162 | ||
169 | spin_lock_bh(&e->lock); | 163 | spin_lock_bh(&e->lock); |
170 | if (e->arpq_head) | 164 | if (!skb_queue_empty(&e->arpq)) |
171 | setup_l2e_send_pending(dev, skb, e); | 165 | setup_l2e_send_pending(dev, skb, e); |
172 | else /* we lost the race */ | 166 | else /* we lost the race */ |
173 | __kfree_skb(skb); | 167 | __kfree_skb(skb); |
@@ -357,14 +351,14 @@ EXPORT_SYMBOL(t3_l2t_get); | |||
357 | * XXX: maybe we should abandon the latter behavior and just require a failure | 351 | * XXX: maybe we should abandon the latter behavior and just require a failure |
358 | * handler. | 352 | * handler. |
359 | */ | 353 | */ |
360 | static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq) | 354 | static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff_head *arpq) |
361 | { | 355 | { |
362 | while (arpq) { | 356 | struct sk_buff *skb, *tmp; |
363 | struct sk_buff *skb = arpq; | 357 | |
358 | skb_queue_walk_safe(arpq, skb, tmp) { | ||
364 | struct l2t_skb_cb *cb = L2T_SKB_CB(skb); | 359 | struct l2t_skb_cb *cb = L2T_SKB_CB(skb); |
365 | 360 | ||
366 | arpq = skb->next; | 361 | __skb_unlink(skb, arpq); |
367 | skb->next = NULL; | ||
368 | if (cb->arp_failure_handler) | 362 | if (cb->arp_failure_handler) |
369 | cb->arp_failure_handler(dev, skb); | 363 | cb->arp_failure_handler(dev, skb); |
370 | else | 364 | else |
@@ -378,8 +372,8 @@ static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq) | |||
378 | */ | 372 | */ |
379 | void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) | 373 | void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) |
380 | { | 374 | { |
375 | struct sk_buff_head arpq; | ||
381 | struct l2t_entry *e; | 376 | struct l2t_entry *e; |
382 | struct sk_buff *arpq = NULL; | ||
383 | struct l2t_data *d = L2DATA(dev); | 377 | struct l2t_data *d = L2DATA(dev); |
384 | u32 addr = *(u32 *) neigh->primary_key; | 378 | u32 addr = *(u32 *) neigh->primary_key; |
385 | int ifidx = neigh->dev->ifindex; | 379 | int ifidx = neigh->dev->ifindex; |
@@ -395,6 +389,8 @@ void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) | |||
395 | return; | 389 | return; |
396 | 390 | ||
397 | found: | 391 | found: |
392 | __skb_queue_head_init(&arpq); | ||
393 | |||
398 | read_unlock(&d->lock); | 394 | read_unlock(&d->lock); |
399 | if (atomic_read(&e->refcnt)) { | 395 | if (atomic_read(&e->refcnt)) { |
400 | if (neigh != e->neigh) | 396 | if (neigh != e->neigh) |
@@ -402,8 +398,7 @@ found: | |||
402 | 398 | ||
403 | if (e->state == L2T_STATE_RESOLVING) { | 399 | if (e->state == L2T_STATE_RESOLVING) { |
404 | if (neigh->nud_state & NUD_FAILED) { | 400 | if (neigh->nud_state & NUD_FAILED) { |
405 | arpq = e->arpq_head; | 401 | skb_queue_splice_init(&e->arpq, &arpq); |
406 | e->arpq_head = e->arpq_tail = NULL; | ||
407 | } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE)) | 402 | } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE)) |
408 | setup_l2e_send_pending(dev, NULL, e); | 403 | setup_l2e_send_pending(dev, NULL, e); |
409 | } else { | 404 | } else { |
@@ -415,8 +410,8 @@ found: | |||
415 | } | 410 | } |
416 | spin_unlock_bh(&e->lock); | 411 | spin_unlock_bh(&e->lock); |
417 | 412 | ||
418 | if (arpq) | 413 | if (!skb_queue_empty(&arpq)) |
419 | handle_failed_resolution(dev, arpq); | 414 | handle_failed_resolution(dev, &arpq); |
420 | } | 415 | } |
421 | 416 | ||
422 | struct l2t_data *t3_init_l2t(unsigned int l2t_capacity) | 417 | struct l2t_data *t3_init_l2t(unsigned int l2t_capacity) |
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h index d79001336cfd..fd3eb07e3f40 100644 --- a/drivers/net/cxgb3/l2t.h +++ b/drivers/net/cxgb3/l2t.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -64,8 +64,7 @@ struct l2t_entry { | |||
64 | struct neighbour *neigh; /* associated neighbour */ | 64 | struct neighbour *neigh; /* associated neighbour */ |
65 | struct l2t_entry *first; /* start of hash chain */ | 65 | struct l2t_entry *first; /* start of hash chain */ |
66 | struct l2t_entry *next; /* next l2t_entry on chain */ | 66 | struct l2t_entry *next; /* next l2t_entry on chain */ |
67 | struct sk_buff *arpq_head; /* queue of packets awaiting resolution */ | 67 | struct sk_buff_head arpq; /* queue of packets awaiting resolution */ |
68 | struct sk_buff *arpq_tail; | ||
69 | spinlock_t lock; | 68 | spinlock_t lock; |
70 | atomic_t refcnt; /* entry reference count */ | 69 | atomic_t refcnt; /* entry reference count */ |
71 | u8 dmac[6]; /* neighbour's MAC address */ | 70 | u8 dmac[6]; /* neighbour's MAC address */ |
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c index 4c4d6e877ea6..3b5517b8fbde 100644 --- a/drivers/net/cxgb3/mc5.c +++ b/drivers/net/cxgb3/mc5.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 4bda27c551c9..a035d5c24442 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h | |||
@@ -573,6 +573,10 @@ | |||
573 | #define V_GPIO10(x) ((x) << S_GPIO10) | 573 | #define V_GPIO10(x) ((x) << S_GPIO10) |
574 | #define F_GPIO10 V_GPIO10(1U) | 574 | #define F_GPIO10 V_GPIO10(1U) |
575 | 575 | ||
576 | #define S_GPIO9 9 | ||
577 | #define V_GPIO9(x) ((x) << S_GPIO9) | ||
578 | #define F_GPIO9 V_GPIO9(1U) | ||
579 | |||
576 | #define S_GPIO7 7 | 580 | #define S_GPIO7 7 |
577 | #define V_GPIO7(x) ((x) << S_GPIO7) | 581 | #define V_GPIO7(x) ((x) << S_GPIO7) |
578 | #define F_GPIO7 V_GPIO7(1U) | 582 | #define F_GPIO7 V_GPIO7(1U) |
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 1b0861d73ab7..c6480be0bc1f 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -351,7 +351,8 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) | |||
351 | pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), | 351 | pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), |
352 | q->buf_size, PCI_DMA_FROMDEVICE); | 352 | q->buf_size, PCI_DMA_FROMDEVICE); |
353 | if (q->use_pages) { | 353 | if (q->use_pages) { |
354 | put_page(d->pg_chunk.page); | 354 | if (d->pg_chunk.page) |
355 | put_page(d->pg_chunk.page); | ||
355 | d->pg_chunk.page = NULL; | 356 | d->pg_chunk.page = NULL; |
356 | } else { | 357 | } else { |
357 | kfree_skb(d->skb); | 358 | kfree_skb(d->skb); |
@@ -583,7 +584,7 @@ static void t3_reset_qset(struct sge_qset *q) | |||
583 | memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET); | 584 | memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET); |
584 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); | 585 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); |
585 | q->txq_stopped = 0; | 586 | q->txq_stopped = 0; |
586 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); | 587 | q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */ |
587 | kfree(q->lro_frag_tbl); | 588 | kfree(q->lro_frag_tbl); |
588 | q->lro_nfrags = q->lro_frag_len = 0; | 589 | q->lro_nfrags = q->lro_frag_len = 0; |
589 | } | 590 | } |
@@ -603,9 +604,6 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) | |||
603 | int i; | 604 | int i; |
604 | struct pci_dev *pdev = adapter->pdev; | 605 | struct pci_dev *pdev = adapter->pdev; |
605 | 606 | ||
606 | if (q->tx_reclaim_timer.function) | ||
607 | del_timer_sync(&q->tx_reclaim_timer); | ||
608 | |||
609 | for (i = 0; i < SGE_RXQ_PER_SET; ++i) | 607 | for (i = 0; i < SGE_RXQ_PER_SET; ++i) |
610 | if (q->fl[i].desc) { | 608 | if (q->fl[i].desc) { |
611 | spin_lock_irq(&adapter->sge.reg_lock); | 609 | spin_lock_irq(&adapter->sge.reg_lock); |
@@ -1704,16 +1702,15 @@ int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb) | |||
1704 | */ | 1702 | */ |
1705 | static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb) | 1703 | static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb) |
1706 | { | 1704 | { |
1707 | skb->next = skb->prev = NULL; | 1705 | int was_empty = skb_queue_empty(&q->rx_queue); |
1708 | if (q->rx_tail) | 1706 | |
1709 | q->rx_tail->next = skb; | 1707 | __skb_queue_tail(&q->rx_queue, skb); |
1710 | else { | 1708 | |
1709 | if (was_empty) { | ||
1711 | struct sge_qset *qs = rspq_to_qset(q); | 1710 | struct sge_qset *qs = rspq_to_qset(q); |
1712 | 1711 | ||
1713 | napi_schedule(&qs->napi); | 1712 | napi_schedule(&qs->napi); |
1714 | q->rx_head = skb; | ||
1715 | } | 1713 | } |
1716 | q->rx_tail = skb; | ||
1717 | } | 1714 | } |
1718 | 1715 | ||
1719 | /** | 1716 | /** |
@@ -1754,26 +1751,29 @@ static int ofld_poll(struct napi_struct *napi, int budget) | |||
1754 | int work_done = 0; | 1751 | int work_done = 0; |
1755 | 1752 | ||
1756 | while (work_done < budget) { | 1753 | while (work_done < budget) { |
1757 | struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE]; | 1754 | struct sk_buff *skb, *tmp, *skbs[RX_BUNDLE_SIZE]; |
1755 | struct sk_buff_head queue; | ||
1758 | int ngathered; | 1756 | int ngathered; |
1759 | 1757 | ||
1760 | spin_lock_irq(&q->lock); | 1758 | spin_lock_irq(&q->lock); |
1761 | head = q->rx_head; | 1759 | __skb_queue_head_init(&queue); |
1762 | if (!head) { | 1760 | skb_queue_splice_init(&q->rx_queue, &queue); |
1761 | if (skb_queue_empty(&queue)) { | ||
1763 | napi_complete(napi); | 1762 | napi_complete(napi); |
1764 | spin_unlock_irq(&q->lock); | 1763 | spin_unlock_irq(&q->lock); |
1765 | return work_done; | 1764 | return work_done; |
1766 | } | 1765 | } |
1767 | |||
1768 | tail = q->rx_tail; | ||
1769 | q->rx_head = q->rx_tail = NULL; | ||
1770 | spin_unlock_irq(&q->lock); | 1766 | spin_unlock_irq(&q->lock); |
1771 | 1767 | ||
1772 | for (ngathered = 0; work_done < budget && head; work_done++) { | 1768 | ngathered = 0; |
1773 | prefetch(head->data); | 1769 | skb_queue_walk_safe(&queue, skb, tmp) { |
1774 | skbs[ngathered] = head; | 1770 | if (work_done >= budget) |
1775 | head = head->next; | 1771 | break; |
1776 | skbs[ngathered]->next = NULL; | 1772 | work_done++; |
1773 | |||
1774 | __skb_unlink(skb, &queue); | ||
1775 | prefetch(skb->data); | ||
1776 | skbs[ngathered] = skb; | ||
1777 | if (++ngathered == RX_BUNDLE_SIZE) { | 1777 | if (++ngathered == RX_BUNDLE_SIZE) { |
1778 | q->offload_bundles++; | 1778 | q->offload_bundles++; |
1779 | adapter->tdev.recv(&adapter->tdev, skbs, | 1779 | adapter->tdev.recv(&adapter->tdev, skbs, |
@@ -1781,12 +1781,10 @@ static int ofld_poll(struct napi_struct *napi, int budget) | |||
1781 | ngathered = 0; | 1781 | ngathered = 0; |
1782 | } | 1782 | } |
1783 | } | 1783 | } |
1784 | if (head) { /* splice remaining packets back onto Rx queue */ | 1784 | if (!skb_queue_empty(&queue)) { |
1785 | /* splice remaining packets back onto Rx queue */ | ||
1785 | spin_lock_irq(&q->lock); | 1786 | spin_lock_irq(&q->lock); |
1786 | tail->next = q->rx_head; | 1787 | skb_queue_splice(&queue, &q->rx_queue); |
1787 | if (!q->rx_head) | ||
1788 | q->rx_tail = tail; | ||
1789 | q->rx_head = head; | ||
1790 | spin_unlock_irq(&q->lock); | 1788 | spin_unlock_irq(&q->lock); |
1791 | } | 1789 | } |
1792 | deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered); | 1790 | deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered); |
@@ -1937,38 +1935,6 @@ static inline int lro_frame_ok(const struct cpl_rx_pkt *p) | |||
1937 | eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); | 1935 | eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); |
1938 | } | 1936 | } |
1939 | 1937 | ||
1940 | #define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\ | ||
1941 | TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\ | ||
1942 | TCP_FLAG_SYN | TCP_FLAG_FIN) | ||
1943 | #define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\ | ||
1944 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP) | ||
1945 | |||
1946 | /** | ||
1947 | * lro_segment_ok - check if a TCP segment is eligible for LRO | ||
1948 | * @tcph: the TCP header of the packet | ||
1949 | * | ||
1950 | * Returns true if a TCP packet is eligible for LRO. This requires that | ||
1951 | * the packet have only the ACK flag set and no TCP options besides | ||
1952 | * time stamps. | ||
1953 | */ | ||
1954 | static inline int lro_segment_ok(const struct tcphdr *tcph) | ||
1955 | { | ||
1956 | int optlen; | ||
1957 | |||
1958 | if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK)) | ||
1959 | return 0; | ||
1960 | |||
1961 | optlen = (tcph->doff << 2) - sizeof(*tcph); | ||
1962 | if (optlen) { | ||
1963 | const u32 *opt = (const u32 *)(tcph + 1); | ||
1964 | |||
1965 | if (optlen != TCPOLEN_TSTAMP_ALIGNED || | ||
1966 | *opt != htonl(TSTAMP_WORD) || !opt[2]) | ||
1967 | return 0; | ||
1968 | } | ||
1969 | return 1; | ||
1970 | } | ||
1971 | |||
1972 | static int t3_get_lro_header(void **eh, void **iph, void **tcph, | 1938 | static int t3_get_lro_header(void **eh, void **iph, void **tcph, |
1973 | u64 *hdr_flags, void *priv) | 1939 | u64 *hdr_flags, void *priv) |
1974 | { | 1940 | { |
@@ -1981,9 +1947,6 @@ static int t3_get_lro_header(void **eh, void **iph, void **tcph, | |||
1981 | *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); | 1947 | *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); |
1982 | *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); | 1948 | *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); |
1983 | 1949 | ||
1984 | if (!lro_segment_ok(*tcph)) | ||
1985 | return -1; | ||
1986 | |||
1987 | *hdr_flags = LRO_IPV4 | LRO_TCP; | 1950 | *hdr_flags = LRO_IPV4 | LRO_TCP; |
1988 | return 0; | 1951 | return 0; |
1989 | } | 1952 | } |
@@ -2878,9 +2841,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2878 | struct net_lro_mgr *lro_mgr = &q->lro_mgr; | 2841 | struct net_lro_mgr *lro_mgr = &q->lro_mgr; |
2879 | 2842 | ||
2880 | init_qset_cntxt(q, id); | 2843 | init_qset_cntxt(q, id); |
2881 | init_timer(&q->tx_reclaim_timer); | 2844 | setup_timer(&q->tx_reclaim_timer, sge_timer_cb, (unsigned long)q); |
2882 | q->tx_reclaim_timer.data = (unsigned long)q; | ||
2883 | q->tx_reclaim_timer.function = sge_timer_cb; | ||
2884 | 2845 | ||
2885 | q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size, | 2846 | q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size, |
2886 | sizeof(struct rx_desc), | 2847 | sizeof(struct rx_desc), |
@@ -2934,6 +2895,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2934 | q->rspq.gen = 1; | 2895 | q->rspq.gen = 1; |
2935 | q->rspq.size = p->rspq_size; | 2896 | q->rspq.size = p->rspq_size; |
2936 | spin_lock_init(&q->rspq.lock); | 2897 | spin_lock_init(&q->rspq.lock); |
2898 | skb_queue_head_init(&q->rspq.rx_queue); | ||
2937 | 2899 | ||
2938 | q->txq[TXQ_ETH].stop_thres = nports * | 2900 | q->txq[TXQ_ETH].stop_thres = nports * |
2939 | flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); | 2901 | flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); |
@@ -3043,6 +3005,24 @@ err: | |||
3043 | } | 3005 | } |
3044 | 3006 | ||
3045 | /** | 3007 | /** |
3008 | * t3_stop_sge_timers - stop SGE timer call backs | ||
3009 | * @adap: the adapter | ||
3010 | * | ||
3011 | * Stops each SGE queue set's timer call back | ||
3012 | */ | ||
3013 | void t3_stop_sge_timers(struct adapter *adap) | ||
3014 | { | ||
3015 | int i; | ||
3016 | |||
3017 | for (i = 0; i < SGE_QSETS; ++i) { | ||
3018 | struct sge_qset *q = &adap->sge.qs[i]; | ||
3019 | |||
3020 | if (q->tx_reclaim_timer.function) | ||
3021 | del_timer_sync(&q->tx_reclaim_timer); | ||
3022 | } | ||
3023 | } | ||
3024 | |||
3025 | /** | ||
3046 | * t3_free_sge_resources - free SGE resources | 3026 | * t3_free_sge_resources - free SGE resources |
3047 | * @adap: the adapter | 3027 | * @adap: the adapter |
3048 | * | 3028 | * |
diff --git a/drivers/net/cxgb3/t3_cpl.h b/drivers/net/cxgb3/t3_cpl.h index 917970ed24a1..852c399a8b0a 100644 --- a/drivers/net/cxgb3/t3_cpl.h +++ b/drivers/net/cxgb3/t3_cpl.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 04c0e90119af..968f64be3743 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -194,21 +194,18 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, | |||
194 | static void mi1_init(struct adapter *adap, const struct adapter_info *ai) | 194 | static void mi1_init(struct adapter *adap, const struct adapter_info *ai) |
195 | { | 195 | { |
196 | u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; | 196 | u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; |
197 | u32 val = F_PREEN | V_MDIINV(ai->mdiinv) | V_MDIEN(ai->mdien) | | 197 | u32 val = F_PREEN | V_CLKDIV(clkdiv); |
198 | V_CLKDIV(clkdiv); | ||
199 | 198 | ||
200 | if (!(ai->caps & SUPPORTED_10000baseT_Full)) | ||
201 | val |= V_ST(1); | ||
202 | t3_write_reg(adap, A_MI1_CFG, val); | 199 | t3_write_reg(adap, A_MI1_CFG, val); |
203 | } | 200 | } |
204 | 201 | ||
205 | #define MDIO_ATTEMPTS 10 | 202 | #define MDIO_ATTEMPTS 20 |
206 | 203 | ||
207 | /* | 204 | /* |
208 | * MI1 read/write operations for direct-addressed PHYs. | 205 | * MI1 read/write operations for clause 22 PHYs. |
209 | */ | 206 | */ |
210 | static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, | 207 | static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, |
211 | int reg_addr, unsigned int *valp) | 208 | int reg_addr, unsigned int *valp) |
212 | { | 209 | { |
213 | int ret; | 210 | int ret; |
214 | u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); | 211 | u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); |
@@ -217,16 +214,17 @@ static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
217 | return -EINVAL; | 214 | return -EINVAL; |
218 | 215 | ||
219 | mutex_lock(&adapter->mdio_lock); | 216 | mutex_lock(&adapter->mdio_lock); |
217 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); | ||
220 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 218 | t3_write_reg(adapter, A_MI1_ADDR, addr); |
221 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); | 219 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); |
222 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | 220 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); |
223 | if (!ret) | 221 | if (!ret) |
224 | *valp = t3_read_reg(adapter, A_MI1_DATA); | 222 | *valp = t3_read_reg(adapter, A_MI1_DATA); |
225 | mutex_unlock(&adapter->mdio_lock); | 223 | mutex_unlock(&adapter->mdio_lock); |
226 | return ret; | 224 | return ret; |
227 | } | 225 | } |
228 | 226 | ||
229 | static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, | 227 | static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, |
230 | int reg_addr, unsigned int val) | 228 | int reg_addr, unsigned int val) |
231 | { | 229 | { |
232 | int ret; | 230 | int ret; |
@@ -236,37 +234,51 @@ static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
236 | return -EINVAL; | 234 | return -EINVAL; |
237 | 235 | ||
238 | mutex_lock(&adapter->mdio_lock); | 236 | mutex_lock(&adapter->mdio_lock); |
237 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); | ||
239 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 238 | t3_write_reg(adapter, A_MI1_ADDR, addr); |
240 | t3_write_reg(adapter, A_MI1_DATA, val); | 239 | t3_write_reg(adapter, A_MI1_DATA, val); |
241 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); | 240 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); |
242 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | 241 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); |
243 | mutex_unlock(&adapter->mdio_lock); | 242 | mutex_unlock(&adapter->mdio_lock); |
244 | return ret; | 243 | return ret; |
245 | } | 244 | } |
246 | 245 | ||
247 | static const struct mdio_ops mi1_mdio_ops = { | 246 | static const struct mdio_ops mi1_mdio_ops = { |
248 | mi1_read, | 247 | t3_mi1_read, |
249 | mi1_write | 248 | t3_mi1_write |
250 | }; | 249 | }; |
251 | 250 | ||
252 | /* | 251 | /* |
252 | * Performs the address cycle for clause 45 PHYs. | ||
253 | * Must be called with the MDIO_LOCK held. | ||
254 | */ | ||
255 | static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr, | ||
256 | int reg_addr) | ||
257 | { | ||
258 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
259 | |||
260 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0); | ||
261 | t3_write_reg(adapter, A_MI1_ADDR, addr); | ||
262 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
263 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
264 | return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | ||
265 | MDIO_ATTEMPTS, 10); | ||
266 | } | ||
267 | |||
268 | /* | ||
253 | * MI1 read/write operations for indirect-addressed PHYs. | 269 | * MI1 read/write operations for indirect-addressed PHYs. |
254 | */ | 270 | */ |
255 | static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, | 271 | static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, |
256 | int reg_addr, unsigned int *valp) | 272 | int reg_addr, unsigned int *valp) |
257 | { | 273 | { |
258 | int ret; | 274 | int ret; |
259 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
260 | 275 | ||
261 | mutex_lock(&adapter->mdio_lock); | 276 | mutex_lock(&adapter->mdio_lock); |
262 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 277 | ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); |
263 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
264 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
265 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | ||
266 | if (!ret) { | 278 | if (!ret) { |
267 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); | 279 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); |
268 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | 280 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, |
269 | MDIO_ATTEMPTS, 20); | 281 | MDIO_ATTEMPTS, 10); |
270 | if (!ret) | 282 | if (!ret) |
271 | *valp = t3_read_reg(adapter, A_MI1_DATA); | 283 | *valp = t3_read_reg(adapter, A_MI1_DATA); |
272 | } | 284 | } |
@@ -278,18 +290,14 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
278 | int reg_addr, unsigned int val) | 290 | int reg_addr, unsigned int val) |
279 | { | 291 | { |
280 | int ret; | 292 | int ret; |
281 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
282 | 293 | ||
283 | mutex_lock(&adapter->mdio_lock); | 294 | mutex_lock(&adapter->mdio_lock); |
284 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 295 | ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); |
285 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
286 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
287 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | ||
288 | if (!ret) { | 296 | if (!ret) { |
289 | t3_write_reg(adapter, A_MI1_DATA, val); | 297 | t3_write_reg(adapter, A_MI1_DATA, val); |
290 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); | 298 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); |
291 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | 299 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, |
292 | MDIO_ATTEMPTS, 20); | 300 | MDIO_ATTEMPTS, 10); |
293 | } | 301 | } |
294 | mutex_unlock(&adapter->mdio_lock); | 302 | mutex_unlock(&adapter->mdio_lock); |
295 | return ret; | 303 | return ret; |
@@ -400,6 +408,29 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) | |||
400 | } | 408 | } |
401 | 409 | ||
402 | /** | 410 | /** |
411 | * t3_phy_advertise_fiber - set fiber PHY advertisement register | ||
412 | * @phy: the PHY to operate on | ||
413 | * @advert: bitmap of capabilities the PHY should advertise | ||
414 | * | ||
415 | * Sets a fiber PHY's advertisement register to advertise the | ||
416 | * requested capabilities. | ||
417 | */ | ||
418 | int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert) | ||
419 | { | ||
420 | unsigned int val = 0; | ||
421 | |||
422 | if (advert & ADVERTISED_1000baseT_Half) | ||
423 | val |= ADVERTISE_1000XHALF; | ||
424 | if (advert & ADVERTISED_1000baseT_Full) | ||
425 | val |= ADVERTISE_1000XFULL; | ||
426 | if (advert & ADVERTISED_Pause) | ||
427 | val |= ADVERTISE_1000XPAUSE; | ||
428 | if (advert & ADVERTISED_Asym_Pause) | ||
429 | val |= ADVERTISE_1000XPSE_ASYM; | ||
430 | return mdio_write(phy, 0, MII_ADVERTISE, val); | ||
431 | } | ||
432 | |||
433 | /** | ||
403 | * t3_set_phy_speed_duplex - force PHY speed and duplex | 434 | * t3_set_phy_speed_duplex - force PHY speed and duplex |
404 | * @phy: the PHY to operate on | 435 | * @phy: the PHY to operate on |
405 | * @speed: requested PHY speed | 436 | * @speed: requested PHY speed |
@@ -434,27 +465,52 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) | |||
434 | return mdio_write(phy, 0, MII_BMCR, ctl); | 465 | return mdio_write(phy, 0, MII_BMCR, ctl); |
435 | } | 466 | } |
436 | 467 | ||
468 | int t3_phy_lasi_intr_enable(struct cphy *phy) | ||
469 | { | ||
470 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); | ||
471 | } | ||
472 | |||
473 | int t3_phy_lasi_intr_disable(struct cphy *phy) | ||
474 | { | ||
475 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); | ||
476 | } | ||
477 | |||
478 | int t3_phy_lasi_intr_clear(struct cphy *phy) | ||
479 | { | ||
480 | u32 val; | ||
481 | |||
482 | return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); | ||
483 | } | ||
484 | |||
485 | int t3_phy_lasi_intr_handler(struct cphy *phy) | ||
486 | { | ||
487 | unsigned int status; | ||
488 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); | ||
489 | |||
490 | if (err) | ||
491 | return err; | ||
492 | return (status & 1) ? cphy_cause_link_change : 0; | ||
493 | } | ||
494 | |||
437 | static const struct adapter_info t3_adap_info[] = { | 495 | static const struct adapter_info t3_adap_info[] = { |
438 | {2, 0, 0, 0, | 496 | {2, 0, |
439 | F_GPIO2_OEN | F_GPIO4_OEN | | 497 | F_GPIO2_OEN | F_GPIO4_OEN | |
440 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, | 498 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, |
441 | 0, | ||
442 | &mi1_mdio_ops, "Chelsio PE9000"}, | 499 | &mi1_mdio_ops, "Chelsio PE9000"}, |
443 | {2, 0, 0, 0, | 500 | {2, 0, |
444 | F_GPIO2_OEN | F_GPIO4_OEN | | 501 | F_GPIO2_OEN | F_GPIO4_OEN | |
445 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, | 502 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, |
446 | 0, | ||
447 | &mi1_mdio_ops, "Chelsio T302"}, | 503 | &mi1_mdio_ops, "Chelsio T302"}, |
448 | {1, 0, 0, 0, | 504 | {1, 0, |
449 | F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | | 505 | F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | |
450 | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, | 506 | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, |
451 | 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | 507 | { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, |
452 | &mi1_mdio_ext_ops, "Chelsio T310"}, | 508 | &mi1_mdio_ext_ops, "Chelsio T310"}, |
453 | {2, 0, 0, 0, | 509 | {2, 0, |
454 | F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | | 510 | F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | |
455 | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | | 511 | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | |
456 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, | 512 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, |
457 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | 513 | { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, |
458 | &mi1_mdio_ext_ops, "Chelsio T320"}, | 514 | &mi1_mdio_ext_ops, "Chelsio T320"}, |
459 | }; | 515 | }; |
460 | 516 | ||
@@ -467,29 +523,23 @@ const struct adapter_info *t3_get_adapter_info(unsigned int id) | |||
467 | return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; | 523 | return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; |
468 | } | 524 | } |
469 | 525 | ||
470 | #define CAPS_1G (SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | \ | 526 | struct port_type_info { |
471 | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII) | 527 | int (*phy_prep)(struct cphy *phy, struct adapter *adapter, |
472 | #define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI) | 528 | int phy_addr, const struct mdio_ops *ops); |
529 | }; | ||
473 | 530 | ||
474 | static const struct port_type_info port_types[] = { | 531 | static const struct port_type_info port_types[] = { |
475 | {NULL}, | 532 | { NULL }, |
476 | {t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE, | 533 | { t3_ael1002_phy_prep }, |
477 | "10GBASE-XR"}, | 534 | { t3_vsc8211_phy_prep }, |
478 | {t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, | 535 | { NULL}, |
479 | "10/100/1000BASE-T"}, | 536 | { t3_xaui_direct_phy_prep }, |
480 | {NULL, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, | 537 | { t3_ael2005_phy_prep }, |
481 | "10/100/1000BASE-T"}, | 538 | { t3_qt2045_phy_prep }, |
482 | {t3_xaui_direct_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | 539 | { t3_ael1006_phy_prep }, |
483 | {NULL, CAPS_10G, "10GBASE-KX4"}, | 540 | { NULL }, |
484 | {t3_qt2045_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | ||
485 | {t3_ael1006_phy_prep, CAPS_10G | SUPPORTED_FIBRE, | ||
486 | "10GBASE-SR"}, | ||
487 | {NULL, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | ||
488 | }; | 541 | }; |
489 | 542 | ||
490 | #undef CAPS_1G | ||
491 | #undef CAPS_10G | ||
492 | |||
493 | #define VPD_ENTRY(name, len) \ | 543 | #define VPD_ENTRY(name, len) \ |
494 | u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] | 544 | u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] |
495 | 545 | ||
@@ -1132,6 +1182,15 @@ void t3_link_changed(struct adapter *adapter, int port_id) | |||
1132 | 1182 | ||
1133 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); | 1183 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); |
1134 | 1184 | ||
1185 | if (lc->requested_fc & PAUSE_AUTONEG) | ||
1186 | fc &= lc->requested_fc; | ||
1187 | else | ||
1188 | fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); | ||
1189 | |||
1190 | if (link_ok == lc->link_ok && speed == lc->speed && | ||
1191 | duplex == lc->duplex && fc == lc->fc) | ||
1192 | return; /* nothing changed */ | ||
1193 | |||
1135 | if (link_ok != lc->link_ok && adapter->params.rev > 0 && | 1194 | if (link_ok != lc->link_ok && adapter->params.rev > 0 && |
1136 | uses_xaui(adapter)) { | 1195 | uses_xaui(adapter)) { |
1137 | if (link_ok) | 1196 | if (link_ok) |
@@ -1142,10 +1201,6 @@ void t3_link_changed(struct adapter *adapter, int port_id) | |||
1142 | lc->link_ok = link_ok; | 1201 | lc->link_ok = link_ok; |
1143 | lc->speed = speed < 0 ? SPEED_INVALID : speed; | 1202 | lc->speed = speed < 0 ? SPEED_INVALID : speed; |
1144 | lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; | 1203 | lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; |
1145 | if (lc->requested_fc & PAUSE_AUTONEG) | ||
1146 | fc &= lc->requested_fc; | ||
1147 | else | ||
1148 | fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); | ||
1149 | 1204 | ||
1150 | if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { | 1205 | if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { |
1151 | /* Set MAC speed, duplex, and flow control to match PHY. */ | 1206 | /* Set MAC speed, duplex, and flow control to match PHY. */ |
@@ -1191,7 +1246,6 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) | |||
1191 | fc); | 1246 | fc); |
1192 | /* Also disables autoneg */ | 1247 | /* Also disables autoneg */ |
1193 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); | 1248 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); |
1194 | phy->ops->reset(phy, 0); | ||
1195 | } else | 1249 | } else |
1196 | phy->ops->autoneg_enable(phy); | 1250 | phy->ops->autoneg_enable(phy); |
1197 | } else { | 1251 | } else { |
@@ -1221,7 +1275,7 @@ struct intr_info { | |||
1221 | unsigned int mask; /* bits to check in interrupt status */ | 1275 | unsigned int mask; /* bits to check in interrupt status */ |
1222 | const char *msg; /* message to print or NULL */ | 1276 | const char *msg; /* message to print or NULL */ |
1223 | short stat_idx; /* stat counter to increment or -1 */ | 1277 | short stat_idx; /* stat counter to increment or -1 */ |
1224 | unsigned short fatal:1; /* whether the condition reported is fatal */ | 1278 | unsigned short fatal; /* whether the condition reported is fatal */ |
1225 | }; | 1279 | }; |
1226 | 1280 | ||
1227 | /** | 1281 | /** |
@@ -1682,25 +1736,23 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx) | |||
1682 | */ | 1736 | */ |
1683 | int t3_phy_intr_handler(struct adapter *adapter) | 1737 | int t3_phy_intr_handler(struct adapter *adapter) |
1684 | { | 1738 | { |
1685 | u32 mask, gpi = adapter_info(adapter)->gpio_intr; | ||
1686 | u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); | 1739 | u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); |
1687 | 1740 | ||
1688 | for_each_port(adapter, i) { | 1741 | for_each_port(adapter, i) { |
1689 | struct port_info *p = adap2pinfo(adapter, i); | 1742 | struct port_info *p = adap2pinfo(adapter, i); |
1690 | 1743 | ||
1691 | mask = gpi - (gpi & (gpi - 1)); | 1744 | if (!(p->phy.caps & SUPPORTED_IRQ)) |
1692 | gpi -= mask; | ||
1693 | |||
1694 | if (!(p->port_type->caps & SUPPORTED_IRQ)) | ||
1695 | continue; | 1745 | continue; |
1696 | 1746 | ||
1697 | if (cause & mask) { | 1747 | if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) { |
1698 | int phy_cause = p->phy.ops->intr_handler(&p->phy); | 1748 | int phy_cause = p->phy.ops->intr_handler(&p->phy); |
1699 | 1749 | ||
1700 | if (phy_cause & cphy_cause_link_change) | 1750 | if (phy_cause & cphy_cause_link_change) |
1701 | t3_link_changed(adapter, i); | 1751 | t3_link_changed(adapter, i); |
1702 | if (phy_cause & cphy_cause_fifo_error) | 1752 | if (phy_cause & cphy_cause_fifo_error) |
1703 | p->phy.fifo_errors++; | 1753 | p->phy.fifo_errors++; |
1754 | if (phy_cause & cphy_cause_module_change) | ||
1755 | t3_os_phymod_changed(adapter, i); | ||
1704 | } | 1756 | } |
1705 | } | 1757 | } |
1706 | 1758 | ||
@@ -1763,6 +1815,17 @@ int t3_slow_intr_handler(struct adapter *adapter) | |||
1763 | return 1; | 1815 | return 1; |
1764 | } | 1816 | } |
1765 | 1817 | ||
1818 | static unsigned int calc_gpio_intr(struct adapter *adap) | ||
1819 | { | ||
1820 | unsigned int i, gpi_intr = 0; | ||
1821 | |||
1822 | for_each_port(adap, i) | ||
1823 | if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) && | ||
1824 | adapter_info(adap)->gpio_intr[i]) | ||
1825 | gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i]; | ||
1826 | return gpi_intr; | ||
1827 | } | ||
1828 | |||
1766 | /** | 1829 | /** |
1767 | * t3_intr_enable - enable interrupts | 1830 | * t3_intr_enable - enable interrupts |
1768 | * @adapter: the adapter whose interrupts should be enabled | 1831 | * @adapter: the adapter whose interrupts should be enabled |
@@ -1805,10 +1868,8 @@ void t3_intr_enable(struct adapter *adapter) | |||
1805 | t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); | 1868 | t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); |
1806 | } | 1869 | } |
1807 | 1870 | ||
1808 | t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, | 1871 | t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter)); |
1809 | adapter_info(adapter)->gpio_intr); | 1872 | |
1810 | t3_write_reg(adapter, A_T3DBG_INT_ENABLE, | ||
1811 | adapter_info(adapter)->gpio_intr); | ||
1812 | if (is_pcie(adapter)) | 1873 | if (is_pcie(adapter)) |
1813 | t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); | 1874 | t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); |
1814 | else | 1875 | else |
@@ -3329,6 +3390,8 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) | |||
3329 | init_hw_for_avail_ports(adapter, adapter->params.nports); | 3390 | init_hw_for_avail_ports(adapter, adapter->params.nports); |
3330 | t3_sge_init(adapter, &adapter->params.sge); | 3391 | t3_sge_init(adapter, &adapter->params.sge); |
3331 | 3392 | ||
3393 | t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter)); | ||
3394 | |||
3332 | t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); | 3395 | t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); |
3333 | t3_write_reg(adapter, A_CIM_BOOT_CFG, | 3396 | t3_write_reg(adapter, A_CIM_BOOT_CFG, |
3334 | V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); | 3397 | V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); |
@@ -3488,7 +3551,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) | |||
3488 | * Older PCIe cards lose their config space during reset, PCI-X | 3551 | * Older PCIe cards lose their config space during reset, PCI-X |
3489 | * ones don't. | 3552 | * ones don't. |
3490 | */ | 3553 | */ |
3491 | static int t3_reset_adapter(struct adapter *adapter) | 3554 | int t3_reset_adapter(struct adapter *adapter) |
3492 | { | 3555 | { |
3493 | int i, save_and_restore_pcie = | 3556 | int i, save_and_restore_pcie = |
3494 | adapter->params.rev < T3_REV_B2 && is_pcie(adapter); | 3557 | adapter->params.rev < T3_REV_B2 && is_pcie(adapter); |
@@ -3556,7 +3619,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3556 | int reset) | 3619 | int reset) |
3557 | { | 3620 | { |
3558 | int ret; | 3621 | int ret; |
3559 | unsigned int i, j = 0; | 3622 | unsigned int i, j = -1; |
3560 | 3623 | ||
3561 | get_pci_mode(adapter, &adapter->params.pci); | 3624 | get_pci_mode(adapter, &adapter->params.pci); |
3562 | 3625 | ||
@@ -3620,16 +3683,18 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3620 | 3683 | ||
3621 | for_each_port(adapter, i) { | 3684 | for_each_port(adapter, i) { |
3622 | u8 hw_addr[6]; | 3685 | u8 hw_addr[6]; |
3686 | const struct port_type_info *pti; | ||
3623 | struct port_info *p = adap2pinfo(adapter, i); | 3687 | struct port_info *p = adap2pinfo(adapter, i); |
3624 | 3688 | ||
3625 | while (!adapter->params.vpd.port_type[j]) | 3689 | while (!adapter->params.vpd.port_type[++j]) |
3626 | ++j; | 3690 | ; |
3627 | 3691 | ||
3628 | p->port_type = &port_types[adapter->params.vpd.port_type[j]]; | 3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; |
3629 | p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3693 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, |
3630 | ai->mdio_ops); | 3694 | ai->mdio_ops); |
3695 | if (ret) | ||
3696 | return ret; | ||
3631 | mac_prep(&p->mac, adapter, j); | 3697 | mac_prep(&p->mac, adapter, j); |
3632 | ++j; | ||
3633 | 3698 | ||
3634 | /* | 3699 | /* |
3635 | * The VPD EEPROM stores the base Ethernet address for the | 3700 | * The VPD EEPROM stores the base Ethernet address for the |
@@ -3643,9 +3708,9 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3643 | ETH_ALEN); | 3708 | ETH_ALEN); |
3644 | memcpy(adapter->port[i]->perm_addr, hw_addr, | 3709 | memcpy(adapter->port[i]->perm_addr, hw_addr, |
3645 | ETH_ALEN); | 3710 | ETH_ALEN); |
3646 | init_link_config(&p->link_config, p->port_type->caps); | 3711 | init_link_config(&p->link_config, p->phy.caps); |
3647 | p->phy.ops->power_down(&p->phy, 1); | 3712 | p->phy.ops->power_down(&p->phy, 1); |
3648 | if (!(p->port_type->caps & SUPPORTED_IRQ)) | 3713 | if (!(p->phy.caps & SUPPORTED_IRQ)) |
3649 | adapter->params.linkpoll_period = 10; | 3714 | adapter->params.linkpoll_period = 10; |
3650 | } | 3715 | } |
3651 | 3716 | ||
@@ -3661,7 +3726,7 @@ void t3_led_ready(struct adapter *adapter) | |||
3661 | int t3_replay_prep_adapter(struct adapter *adapter) | 3726 | int t3_replay_prep_adapter(struct adapter *adapter) |
3662 | { | 3727 | { |
3663 | const struct adapter_info *ai = adapter->params.info; | 3728 | const struct adapter_info *ai = adapter->params.info; |
3664 | unsigned int i, j = 0; | 3729 | unsigned int i, j = -1; |
3665 | int ret; | 3730 | int ret; |
3666 | 3731 | ||
3667 | early_hw_init(adapter, ai); | 3732 | early_hw_init(adapter, ai); |
@@ -3670,15 +3735,17 @@ int t3_replay_prep_adapter(struct adapter *adapter) | |||
3670 | return ret; | 3735 | return ret; |
3671 | 3736 | ||
3672 | for_each_port(adapter, i) { | 3737 | for_each_port(adapter, i) { |
3738 | const struct port_type_info *pti; | ||
3673 | struct port_info *p = adap2pinfo(adapter, i); | 3739 | struct port_info *p = adap2pinfo(adapter, i); |
3674 | while (!adapter->params.vpd.port_type[j]) | ||
3675 | ++j; | ||
3676 | 3740 | ||
3677 | p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3741 | while (!adapter->params.vpd.port_type[++j]) |
3678 | ai->mdio_ops); | 3742 | ; |
3679 | 3743 | ||
3744 | pti = &port_types[adapter->params.vpd.port_type[j]]; | ||
3745 | ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL); | ||
3746 | if (ret) | ||
3747 | return ret; | ||
3680 | p->phy.ops->power_down(&p->phy, 1); | 3748 | p->phy.ops->power_down(&p->phy, 1); |
3681 | ++j; | ||
3682 | } | 3749 | } |
3683 | 3750 | ||
3684 | return 0; | 3751 | return 0; |
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h index 0a21cfbd2b21..be55e9ae74d1 100644 --- a/drivers/net/cxgb3/t3cdev.h +++ b/drivers/net/cxgb3/t3cdev.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006-2007 Chelsio Communications. All rights reserved. | 2 | * Copyright (C) 2006-2008 Chelsio Communications. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 29db711303b9..bb8698a86754 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -35,7 +35,7 @@ | |||
35 | #define DRV_DESC "Chelsio T3 Network Driver" | 35 | #define DRV_DESC "Chelsio T3 Network Driver" |
36 | #define DRV_NAME "cxgb3" | 36 | #define DRV_NAME "cxgb3" |
37 | /* Driver version */ | 37 | /* Driver version */ |
38 | #define DRV_VERSION "1.0-ko" | 38 | #define DRV_VERSION "1.1.0-ko" |
39 | 39 | ||
40 | /* Firmware version */ | 40 | /* Firmware version */ |
41 | #define FW_VERSION_MAJOR 7 | 41 | #define FW_VERSION_MAJOR 7 |
diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/cxgb3/vsc8211.c index eee4285b31be..33f956bd6b59 100644 --- a/drivers/net/cxgb3/vsc8211.c +++ b/drivers/net/cxgb3/vsc8211.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -33,28 +33,40 @@ | |||
33 | 33 | ||
34 | /* VSC8211 PHY specific registers. */ | 34 | /* VSC8211 PHY specific registers. */ |
35 | enum { | 35 | enum { |
36 | VSC8211_SIGDET_CTRL = 19, | ||
37 | VSC8211_EXT_CTRL = 23, | ||
36 | VSC8211_INTR_ENABLE = 25, | 38 | VSC8211_INTR_ENABLE = 25, |
37 | VSC8211_INTR_STATUS = 26, | 39 | VSC8211_INTR_STATUS = 26, |
40 | VSC8211_LED_CTRL = 27, | ||
38 | VSC8211_AUX_CTRL_STAT = 28, | 41 | VSC8211_AUX_CTRL_STAT = 28, |
42 | VSC8211_EXT_PAGE_AXS = 31, | ||
39 | }; | 43 | }; |
40 | 44 | ||
41 | enum { | 45 | enum { |
42 | VSC_INTR_RX_ERR = 1 << 0, | 46 | VSC_INTR_RX_ERR = 1 << 0, |
43 | VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */ | 47 | VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */ |
44 | VSC_INTR_CABLE = 1 << 2, /* cable impairment */ | 48 | VSC_INTR_CABLE = 1 << 2, /* cable impairment */ |
45 | VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */ | 49 | VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */ |
46 | VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */ | 50 | VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */ |
47 | VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */ | 51 | VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */ |
48 | VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */ | 52 | VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */ |
49 | VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */ | 53 | VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */ |
50 | VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */ | 54 | VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */ |
51 | VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */ | 55 | VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */ |
52 | VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */ | 56 | VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */ |
53 | VSC_INTR_LINK_CHG = 1 << 13, /* link change */ | 57 | VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */ |
54 | VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */ | 58 | VSC_INTR_LINK_CHG = 1 << 13, /* link change */ |
59 | VSC_INTR_SPD_CHG = 1 << 14, /* speed change */ | ||
60 | VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */ | ||
61 | }; | ||
62 | |||
63 | enum { | ||
64 | VSC_CTRL_CLAUSE37_VIEW = 1 << 4, /* Switch to Clause 37 view */ | ||
65 | VSC_CTRL_MEDIA_MODE_HI = 0xf000 /* High part of media mode select */ | ||
55 | }; | 66 | }; |
56 | 67 | ||
57 | #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ | 68 | #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ |
69 | VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \ | ||
58 | VSC_INTR_NEG_DONE) | 70 | VSC_INTR_NEG_DONE) |
59 | #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ | 71 | #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ |
60 | VSC_INTR_ENABLE) | 72 | VSC_INTR_ENABLE) |
@@ -184,6 +196,112 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, | |||
184 | return 0; | 196 | return 0; |
185 | } | 197 | } |
186 | 198 | ||
199 | static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, | ||
200 | int *speed, int *duplex, int *fc) | ||
201 | { | ||
202 | unsigned int bmcr, status, lpa, adv; | ||
203 | int err, sp = -1, dplx = -1, pause = 0; | ||
204 | |||
205 | err = mdio_read(cphy, 0, MII_BMCR, &bmcr); | ||
206 | if (!err) | ||
207 | err = mdio_read(cphy, 0, MII_BMSR, &status); | ||
208 | if (err) | ||
209 | return err; | ||
210 | |||
211 | if (link_ok) { | ||
212 | /* | ||
213 | * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it | ||
214 | * once more to get the current link state. | ||
215 | */ | ||
216 | if (!(status & BMSR_LSTATUS)) | ||
217 | err = mdio_read(cphy, 0, MII_BMSR, &status); | ||
218 | if (err) | ||
219 | return err; | ||
220 | *link_ok = (status & BMSR_LSTATUS) != 0; | ||
221 | } | ||
222 | if (!(bmcr & BMCR_ANENABLE)) { | ||
223 | dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
224 | if (bmcr & BMCR_SPEED1000) | ||
225 | sp = SPEED_1000; | ||
226 | else if (bmcr & BMCR_SPEED100) | ||
227 | sp = SPEED_100; | ||
228 | else | ||
229 | sp = SPEED_10; | ||
230 | } else if (status & BMSR_ANEGCOMPLETE) { | ||
231 | err = mdio_read(cphy, 0, MII_LPA, &lpa); | ||
232 | if (!err) | ||
233 | err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); | ||
234 | if (err) | ||
235 | return err; | ||
236 | |||
237 | if (adv & lpa & ADVERTISE_1000XFULL) { | ||
238 | dplx = DUPLEX_FULL; | ||
239 | sp = SPEED_1000; | ||
240 | } else if (adv & lpa & ADVERTISE_1000XHALF) { | ||
241 | dplx = DUPLEX_HALF; | ||
242 | sp = SPEED_1000; | ||
243 | } | ||
244 | |||
245 | if (fc && dplx == DUPLEX_FULL) { | ||
246 | if (lpa & adv & ADVERTISE_1000XPAUSE) | ||
247 | pause = PAUSE_RX | PAUSE_TX; | ||
248 | else if ((lpa & ADVERTISE_1000XPAUSE) && | ||
249 | (adv & lpa & ADVERTISE_1000XPSE_ASYM)) | ||
250 | pause = PAUSE_TX; | ||
251 | else if ((lpa & ADVERTISE_1000XPSE_ASYM) && | ||
252 | (adv & ADVERTISE_1000XPAUSE)) | ||
253 | pause = PAUSE_RX; | ||
254 | } | ||
255 | } | ||
256 | if (speed) | ||
257 | *speed = sp; | ||
258 | if (duplex) | ||
259 | *duplex = dplx; | ||
260 | if (fc) | ||
261 | *fc = pause; | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Enable/disable auto MDI/MDI-X in forced link speed mode. | ||
267 | */ | ||
268 | static int vsc8211_set_automdi(struct cphy *phy, int enable) | ||
269 | { | ||
270 | int err; | ||
271 | |||
272 | err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5); | ||
273 | if (err) | ||
274 | return err; | ||
275 | |||
276 | err = mdio_write(phy, 0, 18, 0x12); | ||
277 | if (err) | ||
278 | return err; | ||
279 | |||
280 | err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003); | ||
281 | if (err) | ||
282 | return err; | ||
283 | |||
284 | err = mdio_write(phy, 0, 16, 0x87fa); | ||
285 | if (err) | ||
286 | return err; | ||
287 | |||
288 | err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); | ||
289 | if (err) | ||
290 | return err; | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex) | ||
296 | { | ||
297 | int err; | ||
298 | |||
299 | err = t3_set_phy_speed_duplex(phy, speed, duplex); | ||
300 | if (!err) | ||
301 | err = vsc8211_set_automdi(phy, 1); | ||
302 | return err; | ||
303 | } | ||
304 | |||
187 | static int vsc8211_power_down(struct cphy *cphy, int enable) | 305 | static int vsc8211_power_down(struct cphy *cphy, int enable) |
188 | { | 306 | { |
189 | return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN, | 307 | return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN, |
@@ -221,8 +339,66 @@ static struct cphy_ops vsc8211_ops = { | |||
221 | .power_down = vsc8211_power_down, | 339 | .power_down = vsc8211_power_down, |
222 | }; | 340 | }; |
223 | 341 | ||
224 | void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, | 342 | static struct cphy_ops vsc8211_fiber_ops = { |
225 | int phy_addr, const struct mdio_ops *mdio_ops) | 343 | .reset = vsc8211_reset, |
344 | .intr_enable = vsc8211_intr_enable, | ||
345 | .intr_disable = vsc8211_intr_disable, | ||
346 | .intr_clear = vsc8211_intr_clear, | ||
347 | .intr_handler = vsc8211_intr_handler, | ||
348 | .autoneg_enable = vsc8211_autoneg_enable, | ||
349 | .autoneg_restart = vsc8211_autoneg_restart, | ||
350 | .advertise = t3_phy_advertise_fiber, | ||
351 | .set_speed_duplex = t3_set_phy_speed_duplex, | ||
352 | .get_link_status = vsc8211_get_link_status_fiber, | ||
353 | .power_down = vsc8211_power_down, | ||
354 | }; | ||
355 | |||
356 | int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, | ||
357 | int phy_addr, const struct mdio_ops *mdio_ops) | ||
226 | { | 358 | { |
227 | cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops); | 359 | int err; |
360 | unsigned int val; | ||
361 | |||
362 | cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops, | ||
363 | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | | ||
364 | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII | | ||
365 | SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"); | ||
366 | msleep(20); /* PHY needs ~10ms to start responding to MDIO */ | ||
367 | |||
368 | err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val); | ||
369 | if (err) | ||
370 | return err; | ||
371 | if (val & VSC_CTRL_MEDIA_MODE_HI) { | ||
372 | /* copper interface, just need to configure the LEDs */ | ||
373 | return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100); | ||
374 | } | ||
375 | |||
376 | phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | | ||
377 | SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ; | ||
378 | phy->desc = "1000BASE-X"; | ||
379 | phy->ops = &vsc8211_fiber_ops; | ||
380 | |||
381 | err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1); | ||
382 | if (err) | ||
383 | return err; | ||
384 | |||
385 | err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1); | ||
386 | if (err) | ||
387 | return err; | ||
388 | |||
389 | err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); | ||
390 | if (err) | ||
391 | return err; | ||
392 | |||
393 | err = mdio_write(phy, 0, VSC8211_EXT_CTRL, | ||
394 | val | VSC_CTRL_CLAUSE37_VIEW); | ||
395 | if (err) | ||
396 | return err; | ||
397 | |||
398 | err = vsc8211_reset(phy, 0); | ||
399 | if (err) | ||
400 | return err; | ||
401 | |||
402 | udelay(5); /* delay after reset before next SMI */ | ||
403 | return 0; | ||
228 | } | 404 | } |
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index ffdc0a1892bd..9d7786937aad 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |