diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 2196 |
1 files changed, 1593 insertions, 603 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index c43d06b8de9b..96a3bc6426e2 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -38,242 +38,262 @@ | |||
38 | 38 | ||
39 | #include <net/ip.h> | 39 | #include <net/ip.h> |
40 | 40 | ||
41 | struct netxen_recv_crb recv_crb_registers[] = { | 41 | #define MASK(n) ((1ULL<<(n))-1) |
42 | /* | 42 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) |
43 | * Instance 0. | 43 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) |
44 | */ | 44 | #define MS_WIN(addr) (addr & 0x0ffc0000) |
45 | { | 45 | |
46 | /* rcv_desc_crb: */ | 46 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) |
47 | { | 47 | |
48 | { | 48 | #define CRB_BLK(off) ((off >> 20) & 0x3f) |
49 | /* crb_rcv_producer_offset: */ | 49 | #define CRB_SUBBLK(off) ((off >> 16) & 0xf) |
50 | NETXEN_NIC_REG(0x100), | 50 | #define CRB_WINDOW_2M (0x130060) |
51 | /* crb_rcv_consumer_offset: */ | 51 | #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) |
52 | NETXEN_NIC_REG(0x104), | 52 | #define CRB_INDIRECT_2M (0x1e0000UL) |
53 | /* crb_gloablrcv_ring: */ | 53 | |
54 | NETXEN_NIC_REG(0x108), | 54 | #define CRB_WIN_LOCK_TIMEOUT 100000000 |
55 | /* crb_rcv_ring_size */ | 55 | static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { |
56 | NETXEN_NIC_REG(0x10c), | 56 | {{{0, 0, 0, 0} } }, /* 0: PCI */ |
57 | 57 | {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ | |
58 | }, | 58 | {1, 0x0110000, 0x0120000, 0x130000}, |
59 | /* Jumbo frames */ | 59 | {1, 0x0120000, 0x0122000, 0x124000}, |
60 | { | 60 | {1, 0x0130000, 0x0132000, 0x126000}, |
61 | /* crb_rcv_producer_offset: */ | 61 | {1, 0x0140000, 0x0142000, 0x128000}, |
62 | NETXEN_NIC_REG(0x110), | 62 | {1, 0x0150000, 0x0152000, 0x12a000}, |
63 | /* crb_rcv_consumer_offset: */ | 63 | {1, 0x0160000, 0x0170000, 0x110000}, |
64 | NETXEN_NIC_REG(0x114), | 64 | {1, 0x0170000, 0x0172000, 0x12e000}, |
65 | /* crb_gloablrcv_ring: */ | 65 | {0, 0x0000000, 0x0000000, 0x000000}, |
66 | NETXEN_NIC_REG(0x118), | 66 | {0, 0x0000000, 0x0000000, 0x000000}, |
67 | /* crb_rcv_ring_size */ | 67 | {0, 0x0000000, 0x0000000, 0x000000}, |
68 | NETXEN_NIC_REG(0x11c), | 68 | {0, 0x0000000, 0x0000000, 0x000000}, |
69 | }, | 69 | {0, 0x0000000, 0x0000000, 0x000000}, |
70 | /* LRO */ | 70 | {0, 0x0000000, 0x0000000, 0x000000}, |
71 | { | 71 | {1, 0x01e0000, 0x01e0800, 0x122000}, |
72 | /* crb_rcv_producer_offset: */ | 72 | {0, 0x0000000, 0x0000000, 0x000000} } }, |
73 | NETXEN_NIC_REG(0x120), | 73 | {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ |
74 | /* crb_rcv_consumer_offset: */ | 74 | {{{0, 0, 0, 0} } }, /* 3: */ |
75 | NETXEN_NIC_REG(0x124), | 75 | {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ |
76 | /* crb_gloablrcv_ring: */ | 76 | {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ |
77 | NETXEN_NIC_REG(0x128), | 77 | {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ |
78 | /* crb_rcv_ring_size */ | 78 | {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ |
79 | NETXEN_NIC_REG(0x12c), | 79 | {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ |
80 | } | 80 | {0, 0x0000000, 0x0000000, 0x000000}, |
81 | }, | 81 | {0, 0x0000000, 0x0000000, 0x000000}, |
82 | /* crb_rcvstatus_ring: */ | 82 | {0, 0x0000000, 0x0000000, 0x000000}, |
83 | NETXEN_NIC_REG(0x130), | 83 | {0, 0x0000000, 0x0000000, 0x000000}, |
84 | /* crb_rcv_status_producer: */ | 84 | {0, 0x0000000, 0x0000000, 0x000000}, |
85 | NETXEN_NIC_REG(0x134), | 85 | {0, 0x0000000, 0x0000000, 0x000000}, |
86 | /* crb_rcv_status_consumer: */ | 86 | {0, 0x0000000, 0x0000000, 0x000000}, |
87 | NETXEN_NIC_REG(0x138), | 87 | {0, 0x0000000, 0x0000000, 0x000000}, |
88 | /* crb_rcvpeg_state: */ | 88 | {0, 0x0000000, 0x0000000, 0x000000}, |
89 | NETXEN_NIC_REG(0x13c), | 89 | {0, 0x0000000, 0x0000000, 0x000000}, |
90 | /* crb_status_ring_size */ | 90 | {0, 0x0000000, 0x0000000, 0x000000}, |
91 | NETXEN_NIC_REG(0x140), | 91 | {0, 0x0000000, 0x0000000, 0x000000}, |
92 | 92 | {0, 0x0000000, 0x0000000, 0x000000}, | |
93 | }, | 93 | {0, 0x0000000, 0x0000000, 0x000000}, |
94 | /* | 94 | {1, 0x08f0000, 0x08f2000, 0x172000} } }, |
95 | * Instance 1, | 95 | {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ |
96 | */ | 96 | {0, 0x0000000, 0x0000000, 0x000000}, |
97 | { | 97 | {0, 0x0000000, 0x0000000, 0x000000}, |
98 | /* rcv_desc_crb: */ | 98 | {0, 0x0000000, 0x0000000, 0x000000}, |
99 | { | 99 | {0, 0x0000000, 0x0000000, 0x000000}, |
100 | { | 100 | {0, 0x0000000, 0x0000000, 0x000000}, |
101 | /* crb_rcv_producer_offset: */ | 101 | {0, 0x0000000, 0x0000000, 0x000000}, |
102 | NETXEN_NIC_REG(0x144), | 102 | {0, 0x0000000, 0x0000000, 0x000000}, |
103 | /* crb_rcv_consumer_offset: */ | 103 | {0, 0x0000000, 0x0000000, 0x000000}, |
104 | NETXEN_NIC_REG(0x148), | 104 | {0, 0x0000000, 0x0000000, 0x000000}, |
105 | /* crb_globalrcv_ring: */ | 105 | {0, 0x0000000, 0x0000000, 0x000000}, |
106 | NETXEN_NIC_REG(0x14c), | 106 | {0, 0x0000000, 0x0000000, 0x000000}, |
107 | /* crb_rcv_ring_size */ | 107 | {0, 0x0000000, 0x0000000, 0x000000}, |
108 | NETXEN_NIC_REG(0x150), | 108 | {0, 0x0000000, 0x0000000, 0x000000}, |
109 | 109 | {0, 0x0000000, 0x0000000, 0x000000}, | |
110 | }, | 110 | {1, 0x09f0000, 0x09f2000, 0x176000} } }, |
111 | /* Jumbo frames */ | 111 | {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ |
112 | { | 112 | {0, 0x0000000, 0x0000000, 0x000000}, |
113 | /* crb_rcv_producer_offset: */ | 113 | {0, 0x0000000, 0x0000000, 0x000000}, |
114 | NETXEN_NIC_REG(0x154), | 114 | {0, 0x0000000, 0x0000000, 0x000000}, |
115 | /* crb_rcv_consumer_offset: */ | 115 | {0, 0x0000000, 0x0000000, 0x000000}, |
116 | NETXEN_NIC_REG(0x158), | 116 | {0, 0x0000000, 0x0000000, 0x000000}, |
117 | /* crb_globalrcv_ring: */ | 117 | {0, 0x0000000, 0x0000000, 0x000000}, |
118 | NETXEN_NIC_REG(0x15c), | 118 | {0, 0x0000000, 0x0000000, 0x000000}, |
119 | /* crb_rcv_ring_size */ | 119 | {0, 0x0000000, 0x0000000, 0x000000}, |
120 | NETXEN_NIC_REG(0x160), | 120 | {0, 0x0000000, 0x0000000, 0x000000}, |
121 | }, | 121 | {0, 0x0000000, 0x0000000, 0x000000}, |
122 | /* LRO */ | 122 | {0, 0x0000000, 0x0000000, 0x000000}, |
123 | { | 123 | {0, 0x0000000, 0x0000000, 0x000000}, |
124 | /* crb_rcv_producer_offset: */ | 124 | {0, 0x0000000, 0x0000000, 0x000000}, |
125 | NETXEN_NIC_REG(0x164), | 125 | {0, 0x0000000, 0x0000000, 0x000000}, |
126 | /* crb_rcv_consumer_offset: */ | 126 | {1, 0x0af0000, 0x0af2000, 0x17a000} } }, |
127 | NETXEN_NIC_REG(0x168), | 127 | {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ |
128 | /* crb_globalrcv_ring: */ | 128 | {0, 0x0000000, 0x0000000, 0x000000}, |
129 | NETXEN_NIC_REG(0x16c), | 129 | {0, 0x0000000, 0x0000000, 0x000000}, |
130 | /* crb_rcv_ring_size */ | 130 | {0, 0x0000000, 0x0000000, 0x000000}, |
131 | NETXEN_NIC_REG(0x170), | 131 | {0, 0x0000000, 0x0000000, 0x000000}, |
132 | } | 132 | {0, 0x0000000, 0x0000000, 0x000000}, |
133 | 133 | {0, 0x0000000, 0x0000000, 0x000000}, | |
134 | }, | 134 | {0, 0x0000000, 0x0000000, 0x000000}, |
135 | /* crb_rcvstatus_ring: */ | 135 | {0, 0x0000000, 0x0000000, 0x000000}, |
136 | NETXEN_NIC_REG(0x174), | 136 | {0, 0x0000000, 0x0000000, 0x000000}, |
137 | /* crb_rcv_status_producer: */ | 137 | {0, 0x0000000, 0x0000000, 0x000000}, |
138 | NETXEN_NIC_REG(0x178), | 138 | {0, 0x0000000, 0x0000000, 0x000000}, |
139 | /* crb_rcv_status_consumer: */ | 139 | {0, 0x0000000, 0x0000000, 0x000000}, |
140 | NETXEN_NIC_REG(0x17c), | 140 | {0, 0x0000000, 0x0000000, 0x000000}, |
141 | /* crb_rcvpeg_state: */ | 141 | {0, 0x0000000, 0x0000000, 0x000000}, |
142 | NETXEN_NIC_REG(0x180), | 142 | {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, |
143 | /* crb_status_ring_size */ | 143 | {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ |
144 | NETXEN_NIC_REG(0x184), | 144 | {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ |
145 | }, | 145 | {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ |
146 | /* | 146 | {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ |
147 | * Instance 2, | 147 | {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ |
148 | */ | 148 | {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ |
149 | { | 149 | {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ |
150 | { | 150 | {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ |
151 | { | 151 | {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ |
152 | /* crb_rcv_producer_offset: */ | 152 | {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ |
153 | NETXEN_NIC_REG(0x1d8), | 153 | {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ |
154 | /* crb_rcv_consumer_offset: */ | 154 | {{{0, 0, 0, 0} } }, /* 23: */ |
155 | NETXEN_NIC_REG(0x1dc), | 155 | {{{0, 0, 0, 0} } }, /* 24: */ |
156 | /* crb_gloablrcv_ring: */ | 156 | {{{0, 0, 0, 0} } }, /* 25: */ |
157 | NETXEN_NIC_REG(0x1f0), | 157 | {{{0, 0, 0, 0} } }, /* 26: */ |
158 | /* crb_rcv_ring_size */ | 158 | {{{0, 0, 0, 0} } }, /* 27: */ |
159 | NETXEN_NIC_REG(0x1f4), | 159 | {{{0, 0, 0, 0} } }, /* 28: */ |
160 | }, | 160 | {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ |
161 | /* Jumbo frames */ | 161 | {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ |
162 | { | 162 | {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ |
163 | /* crb_rcv_producer_offset: */ | 163 | {{{0} } }, /* 32: PCI */ |
164 | NETXEN_NIC_REG(0x1f8), | 164 | {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ |
165 | /* crb_rcv_consumer_offset: */ | 165 | {1, 0x2110000, 0x2120000, 0x130000}, |
166 | NETXEN_NIC_REG(0x1fc), | 166 | {1, 0x2120000, 0x2122000, 0x124000}, |
167 | /* crb_gloablrcv_ring: */ | 167 | {1, 0x2130000, 0x2132000, 0x126000}, |
168 | NETXEN_NIC_REG(0x200), | 168 | {1, 0x2140000, 0x2142000, 0x128000}, |
169 | /* crb_rcv_ring_size */ | 169 | {1, 0x2150000, 0x2152000, 0x12a000}, |
170 | NETXEN_NIC_REG(0x204), | 170 | {1, 0x2160000, 0x2170000, 0x110000}, |
171 | }, | 171 | {1, 0x2170000, 0x2172000, 0x12e000}, |
172 | /* LRO */ | 172 | {0, 0x0000000, 0x0000000, 0x000000}, |
173 | { | 173 | {0, 0x0000000, 0x0000000, 0x000000}, |
174 | /* crb_rcv_producer_offset: */ | 174 | {0, 0x0000000, 0x0000000, 0x000000}, |
175 | NETXEN_NIC_REG(0x208), | 175 | {0, 0x0000000, 0x0000000, 0x000000}, |
176 | /* crb_rcv_consumer_offset: */ | 176 | {0, 0x0000000, 0x0000000, 0x000000}, |
177 | NETXEN_NIC_REG(0x20c), | 177 | {0, 0x0000000, 0x0000000, 0x000000}, |
178 | /* crb_gloablrcv_ring: */ | 178 | {0, 0x0000000, 0x0000000, 0x000000}, |
179 | NETXEN_NIC_REG(0x210), | 179 | {0, 0x0000000, 0x0000000, 0x000000} } }, |
180 | /* crb_rcv_ring_size */ | 180 | {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ |
181 | NETXEN_NIC_REG(0x214), | 181 | {{{0} } }, /* 35: */ |
182 | } | 182 | {{{0} } }, /* 36: */ |
183 | }, | 183 | {{{0} } }, /* 37: */ |
184 | /* crb_rcvstatus_ring: */ | 184 | {{{0} } }, /* 38: */ |
185 | NETXEN_NIC_REG(0x218), | 185 | {{{0} } }, /* 39: */ |
186 | /* crb_rcv_status_producer: */ | 186 | {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ |
187 | NETXEN_NIC_REG(0x21c), | 187 | {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ |
188 | /* crb_rcv_status_consumer: */ | 188 | {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ |
189 | NETXEN_NIC_REG(0x220), | 189 | {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ |
190 | /* crb_rcvpeg_state: */ | 190 | {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ |
191 | NETXEN_NIC_REG(0x224), | 191 | {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ |
192 | /* crb_status_ring_size */ | 192 | {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ |
193 | NETXEN_NIC_REG(0x228), | 193 | {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ |
194 | }, | 194 | {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ |
195 | /* | 195 | {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ |
196 | * Instance 3, | 196 | {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ |
197 | */ | 197 | {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ |
198 | { | 198 | {{{0} } }, /* 52: */ |
199 | { | 199 | {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ |
200 | { | 200 | {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ |
201 | /* crb_rcv_producer_offset: */ | 201 | {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ |
202 | NETXEN_NIC_REG(0x22c), | 202 | {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ |
203 | /* crb_rcv_consumer_offset: */ | 203 | {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ |
204 | NETXEN_NIC_REG(0x230), | 204 | {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ |
205 | /* crb_gloablrcv_ring: */ | 205 | {{{0} } }, /* 59: I2C0 */ |
206 | NETXEN_NIC_REG(0x234), | 206 | {{{0} } }, /* 60: I2C1 */ |
207 | /* crb_rcv_ring_size */ | 207 | {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */ |
208 | NETXEN_NIC_REG(0x238), | 208 | {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ |
209 | }, | 209 | {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ |
210 | /* Jumbo frames */ | ||
211 | { | ||
212 | /* crb_rcv_producer_offset: */ | ||
213 | NETXEN_NIC_REG(0x23c), | ||
214 | /* crb_rcv_consumer_offset: */ | ||
215 | NETXEN_NIC_REG(0x240), | ||
216 | /* crb_gloablrcv_ring: */ | ||
217 | NETXEN_NIC_REG(0x244), | ||
218 | /* crb_rcv_ring_size */ | ||
219 | NETXEN_NIC_REG(0x248), | ||
220 | }, | ||
221 | /* LRO */ | ||
222 | { | ||
223 | /* crb_rcv_producer_offset: */ | ||
224 | NETXEN_NIC_REG(0x24c), | ||
225 | /* crb_rcv_consumer_offset: */ | ||
226 | NETXEN_NIC_REG(0x250), | ||
227 | /* crb_gloablrcv_ring: */ | ||
228 | NETXEN_NIC_REG(0x254), | ||
229 | /* crb_rcv_ring_size */ | ||
230 | NETXEN_NIC_REG(0x258), | ||
231 | } | ||
232 | }, | ||
233 | /* crb_rcvstatus_ring: */ | ||
234 | NETXEN_NIC_REG(0x25c), | ||
235 | /* crb_rcv_status_producer: */ | ||
236 | NETXEN_NIC_REG(0x260), | ||
237 | /* crb_rcv_status_consumer: */ | ||
238 | NETXEN_NIC_REG(0x264), | ||
239 | /* crb_rcvpeg_state: */ | ||
240 | NETXEN_NIC_REG(0x268), | ||
241 | /* crb_status_ring_size */ | ||
242 | NETXEN_NIC_REG(0x26c), | ||
243 | }, | ||
244 | }; | 210 | }; |
245 | 211 | ||
246 | static u64 ctx_addr_sig_regs[][3] = { | 212 | /* |
247 | {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, | 213 | * top 12 bits of crb internal address (hub, agent) |
248 | {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, | 214 | */ |
249 | {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)}, | 215 | static unsigned crb_hub_agt[64] = |
250 | {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)} | 216 | { |
217 | 0, | ||
218 | NETXEN_HW_CRB_HUB_AGT_ADR_PS, | ||
219 | NETXEN_HW_CRB_HUB_AGT_ADR_MN, | ||
220 | NETXEN_HW_CRB_HUB_AGT_ADR_MS, | ||
221 | 0, | ||
222 | NETXEN_HW_CRB_HUB_AGT_ADR_SRE, | ||
223 | NETXEN_HW_CRB_HUB_AGT_ADR_NIU, | ||
224 | NETXEN_HW_CRB_HUB_AGT_ADR_QMN, | ||
225 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN0, | ||
226 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN1, | ||
227 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN2, | ||
228 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN3, | ||
229 | NETXEN_HW_CRB_HUB_AGT_ADR_I2Q, | ||
230 | NETXEN_HW_CRB_HUB_AGT_ADR_TIMR, | ||
231 | NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
232 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN4, | ||
233 | NETXEN_HW_CRB_HUB_AGT_ADR_XDMA, | ||
234 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN0, | ||
235 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN1, | ||
236 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN2, | ||
237 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN3, | ||
238 | NETXEN_HW_CRB_HUB_AGT_ADR_PGND, | ||
239 | NETXEN_HW_CRB_HUB_AGT_ADR_PGNI, | ||
240 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS0, | ||
241 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS1, | ||
242 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS2, | ||
243 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS3, | ||
244 | 0, | ||
245 | NETXEN_HW_CRB_HUB_AGT_ADR_PGSI, | ||
246 | NETXEN_HW_CRB_HUB_AGT_ADR_SN, | ||
247 | 0, | ||
248 | NETXEN_HW_CRB_HUB_AGT_ADR_EG, | ||
249 | 0, | ||
250 | NETXEN_HW_CRB_HUB_AGT_ADR_PS, | ||
251 | NETXEN_HW_CRB_HUB_AGT_ADR_CAM, | ||
252 | 0, | ||
253 | 0, | ||
254 | 0, | ||
255 | 0, | ||
256 | 0, | ||
257 | NETXEN_HW_CRB_HUB_AGT_ADR_TIMR, | ||
258 | 0, | ||
259 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1, | ||
260 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2, | ||
261 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3, | ||
262 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4, | ||
263 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5, | ||
264 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6, | ||
265 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7, | ||
266 | NETXEN_HW_CRB_HUB_AGT_ADR_XDMA, | ||
267 | NETXEN_HW_CRB_HUB_AGT_ADR_I2Q, | ||
268 | NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
269 | 0, | ||
270 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0, | ||
271 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8, | ||
272 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9, | ||
273 | NETXEN_HW_CRB_HUB_AGT_ADR_OCM0, | ||
274 | 0, | ||
275 | NETXEN_HW_CRB_HUB_AGT_ADR_SMB, | ||
276 | NETXEN_HW_CRB_HUB_AGT_ADR_I2C0, | ||
277 | NETXEN_HW_CRB_HUB_AGT_ADR_I2C1, | ||
278 | 0, | ||
279 | NETXEN_HW_CRB_HUB_AGT_ADR_PGNC, | ||
280 | 0, | ||
251 | }; | 281 | }; |
252 | #define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0]) | ||
253 | #define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2]) | ||
254 | #define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1]) | ||
255 | |||
256 | 282 | ||
257 | /* PCI Windowing for DDR regions. */ | 283 | /* PCI Windowing for DDR regions. */ |
258 | 284 | ||
259 | #define ADDR_IN_RANGE(addr, low, high) \ | 285 | #define ADDR_IN_RANGE(addr, low, high) \ |
260 | (((addr) <= (high)) && ((addr) >= (low))) | 286 | (((addr) <= (high)) && ((addr) >= (low))) |
261 | 287 | ||
262 | #define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START) | ||
263 | #define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE) | ||
264 | #define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE | 288 | #define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE |
265 | #define NETXEN_MIN_MTU 64 | 289 | #define NETXEN_MIN_MTU 64 |
266 | #define NETXEN_ETH_FCS_SIZE 4 | 290 | #define NETXEN_ETH_FCS_SIZE 4 |
267 | #define NETXEN_ENET_HEADER_SIZE 14 | 291 | #define NETXEN_ENET_HEADER_SIZE 14 |
268 | #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ | 292 | #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ |
269 | #define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4) | 293 | #define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4) |
270 | #define NETXEN_NIU_HDRSIZE (0x1 << 6) | 294 | #define NETXEN_NIU_HDRSIZE (0x1 << 6) |
271 | #define NETXEN_NIU_TLRSIZE (0x1 << 5) | 295 | #define NETXEN_NIU_TLRSIZE (0x1 << 5) |
272 | 296 | ||
273 | #define lower32(x) ((u32)((x) & 0xffffffff)) | ||
274 | #define upper32(x) \ | ||
275 | ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff)) | ||
276 | |||
277 | #define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL | 297 | #define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL |
278 | #define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL | 298 | #define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL |
279 | #define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL | 299 | #define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL |
@@ -281,10 +301,6 @@ static u64 ctx_addr_sig_regs[][3] = { | |||
281 | 301 | ||
282 | #define NETXEN_NIC_WINDOW_MARGIN 0x100000 | 302 | #define NETXEN_NIC_WINDOW_MARGIN 0x100000 |
283 | 303 | ||
284 | static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter, | ||
285 | unsigned long long addr); | ||
286 | void netxen_free_hw_resources(struct netxen_adapter *adapter); | ||
287 | |||
288 | int netxen_nic_set_mac(struct net_device *netdev, void *p) | 304 | int netxen_nic_set_mac(struct net_device *netdev, void *p) |
289 | { | 305 | { |
290 | struct netxen_adapter *adapter = netdev_priv(netdev); | 306 | struct netxen_adapter *adapter = netdev_priv(netdev); |
@@ -296,266 +312,370 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p) | |||
296 | if (!is_valid_ether_addr(addr->sa_data)) | 312 | if (!is_valid_ether_addr(addr->sa_data)) |
297 | return -EADDRNOTAVAIL; | 313 | return -EADDRNOTAVAIL; |
298 | 314 | ||
299 | DPRINTK(INFO, "valid ether addr\n"); | ||
300 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 315 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
301 | 316 | ||
302 | if (adapter->macaddr_set) | 317 | /* For P3, MAC addr is not set in NIU */ |
303 | adapter->macaddr_set(adapter, addr->sa_data); | 318 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
319 | if (adapter->macaddr_set) | ||
320 | adapter->macaddr_set(adapter, addr->sa_data); | ||
304 | 321 | ||
305 | return 0; | 322 | return 0; |
306 | } | 323 | } |
307 | 324 | ||
308 | /* | 325 | #define NETXEN_UNICAST_ADDR(port, index) \ |
309 | * netxen_nic_set_multi - Multicast | 326 | (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8)) |
310 | */ | 327 | #define NETXEN_MCAST_ADDR(port, index) \ |
311 | void netxen_nic_set_multi(struct net_device *netdev) | 328 | (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8)) |
329 | #define MAC_HI(addr) \ | ||
330 | ((addr[2] << 16) | (addr[1] << 8) | (addr[0])) | ||
331 | #define MAC_LO(addr) \ | ||
332 | ((addr[5] << 16) | (addr[4] << 8) | (addr[3])) | ||
333 | |||
334 | static int | ||
335 | netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) | ||
336 | { | ||
337 | u32 val = 0; | ||
338 | u16 port = adapter->physical_port; | ||
339 | u8 *addr = adapter->netdev->dev_addr; | ||
340 | |||
341 | if (adapter->mc_enabled) | ||
342 | return 0; | ||
343 | |||
344 | adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); | ||
345 | val |= (1UL << (28+port)); | ||
346 | adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); | ||
347 | |||
348 | /* add broadcast addr to filter */ | ||
349 | val = 0xffffff; | ||
350 | netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); | ||
351 | netxen_crb_writelit_adapter(adapter, | ||
352 | NETXEN_UNICAST_ADDR(port, 0)+4, val); | ||
353 | |||
354 | /* add station addr to filter */ | ||
355 | val = MAC_HI(addr); | ||
356 | netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val); | ||
357 | val = MAC_LO(addr); | ||
358 | netxen_crb_writelit_adapter(adapter, | ||
359 | NETXEN_UNICAST_ADDR(port, 1)+4, val); | ||
360 | |||
361 | adapter->mc_enabled = 1; | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int | ||
366 | netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter) | ||
367 | { | ||
368 | u32 val = 0; | ||
369 | u16 port = adapter->physical_port; | ||
370 | u8 *addr = adapter->netdev->dev_addr; | ||
371 | |||
372 | if (!adapter->mc_enabled) | ||
373 | return 0; | ||
374 | |||
375 | adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); | ||
376 | val &= ~(1UL << (28+port)); | ||
377 | adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); | ||
378 | |||
379 | val = MAC_HI(addr); | ||
380 | netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); | ||
381 | val = MAC_LO(addr); | ||
382 | netxen_crb_writelit_adapter(adapter, | ||
383 | NETXEN_UNICAST_ADDR(port, 0)+4, val); | ||
384 | |||
385 | netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); | ||
386 | netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); | ||
387 | |||
388 | adapter->mc_enabled = 0; | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int | ||
393 | netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, | ||
394 | int index, u8 *addr) | ||
395 | { | ||
396 | u32 hi = 0, lo = 0; | ||
397 | u16 port = adapter->physical_port; | ||
398 | |||
399 | lo = MAC_LO(addr); | ||
400 | hi = MAC_HI(addr); | ||
401 | |||
402 | netxen_crb_writelit_adapter(adapter, | ||
403 | NETXEN_MCAST_ADDR(port, index), hi); | ||
404 | netxen_crb_writelit_adapter(adapter, | ||
405 | NETXEN_MCAST_ADDR(port, index)+4, lo); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | void netxen_p2_nic_set_multi(struct net_device *netdev) | ||
312 | { | 411 | { |
313 | struct netxen_adapter *adapter = netdev_priv(netdev); | 412 | struct netxen_adapter *adapter = netdev_priv(netdev); |
314 | struct dev_mc_list *mc_ptr; | 413 | struct dev_mc_list *mc_ptr; |
414 | u8 null_addr[6]; | ||
415 | int index = 0; | ||
416 | |||
417 | memset(null_addr, 0, 6); | ||
315 | 418 | ||
316 | mc_ptr = netdev->mc_list; | ||
317 | if (netdev->flags & IFF_PROMISC) { | 419 | if (netdev->flags & IFF_PROMISC) { |
318 | if (adapter->set_promisc) | 420 | |
319 | adapter->set_promisc(adapter, | 421 | adapter->set_promisc(adapter, |
320 | NETXEN_NIU_PROMISC_MODE); | 422 | NETXEN_NIU_PROMISC_MODE); |
321 | } else { | 423 | |
322 | if (adapter->unset_promisc) | 424 | /* Full promiscuous mode */ |
323 | adapter->unset_promisc(adapter, | 425 | netxen_nic_disable_mcast_filter(adapter); |
324 | NETXEN_NIU_NON_PROMISC_MODE); | 426 | |
427 | return; | ||
428 | } | ||
429 | |||
430 | if (netdev->mc_count == 0) { | ||
431 | adapter->set_promisc(adapter, | ||
432 | NETXEN_NIU_NON_PROMISC_MODE); | ||
433 | netxen_nic_disable_mcast_filter(adapter); | ||
434 | return; | ||
325 | } | 435 | } |
436 | |||
437 | adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE); | ||
438 | if (netdev->flags & IFF_ALLMULTI || | ||
439 | netdev->mc_count > adapter->max_mc_count) { | ||
440 | netxen_nic_disable_mcast_filter(adapter); | ||
441 | return; | ||
442 | } | ||
443 | |||
444 | netxen_nic_enable_mcast_filter(adapter); | ||
445 | |||
446 | for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++) | ||
447 | netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr); | ||
448 | |||
449 | if (index != netdev->mc_count) | ||
450 | printk(KERN_WARNING "%s: %s multicast address count mismatch\n", | ||
451 | netxen_nic_driver_name, netdev->name); | ||
452 | |||
453 | /* Clear out remaining addresses */ | ||
454 | for (; index < adapter->max_mc_count; index++) | ||
455 | netxen_nic_set_mcast_addr(adapter, index, null_addr); | ||
326 | } | 456 | } |
327 | 457 | ||
328 | /* | 458 | static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, |
329 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | 459 | u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list) |
330 | * @returns 0 on success, negative on failure | ||
331 | */ | ||
332 | int netxen_nic_change_mtu(struct net_device *netdev, int mtu) | ||
333 | { | 460 | { |
334 | struct netxen_adapter *adapter = netdev_priv(netdev); | 461 | nx_mac_list_t *cur, *prev; |
335 | int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE; | 462 | |
463 | /* if in del_list, move it to adapter->mac_list */ | ||
464 | for (cur = *del_list, prev = NULL; cur;) { | ||
465 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { | ||
466 | if (prev == NULL) | ||
467 | *del_list = cur->next; | ||
468 | else | ||
469 | prev->next = cur->next; | ||
470 | cur->next = adapter->mac_list; | ||
471 | adapter->mac_list = cur; | ||
472 | return 0; | ||
473 | } | ||
474 | prev = cur; | ||
475 | cur = cur->next; | ||
476 | } | ||
477 | |||
478 | /* make sure to add each mac address only once */ | ||
479 | for (cur = adapter->mac_list; cur; cur = cur->next) { | ||
480 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) | ||
481 | return 0; | ||
482 | } | ||
483 | /* not in del_list, create new entry and add to add_list */ | ||
484 | cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL); | ||
485 | if (cur == NULL) { | ||
486 | printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may" | ||
487 | "not work properly from now.\n", __func__); | ||
488 | return -1; | ||
489 | } | ||
336 | 490 | ||
337 | if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) { | 491 | memcpy(cur->mac_addr, addr, ETH_ALEN); |
338 | printk(KERN_ERR "%s: %s %d is not supported.\n", | 492 | cur->next = *add_list; |
339 | netxen_nic_driver_name, netdev->name, mtu); | 493 | *add_list = cur; |
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int | ||
498 | netxen_send_cmd_descs(struct netxen_adapter *adapter, | ||
499 | struct cmd_desc_type0 *cmd_desc_arr, int nr_elements) | ||
500 | { | ||
501 | uint32_t i, producer; | ||
502 | struct netxen_cmd_buffer *pbuf; | ||
503 | struct cmd_desc_type0 *cmd_desc; | ||
504 | |||
505 | if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) { | ||
506 | printk(KERN_WARNING "%s: Too many command descriptors in a " | ||
507 | "request\n", __func__); | ||
340 | return -EINVAL; | 508 | return -EINVAL; |
341 | } | 509 | } |
342 | 510 | ||
343 | if (adapter->set_mtu) | 511 | i = 0; |
344 | adapter->set_mtu(adapter, mtu); | 512 | |
345 | netdev->mtu = mtu; | 513 | producer = adapter->cmd_producer; |
514 | do { | ||
515 | cmd_desc = &cmd_desc_arr[i]; | ||
516 | |||
517 | pbuf = &adapter->cmd_buf_arr[producer]; | ||
518 | pbuf->mss = 0; | ||
519 | pbuf->total_length = 0; | ||
520 | pbuf->skb = NULL; | ||
521 | pbuf->cmd = 0; | ||
522 | pbuf->frag_count = 0; | ||
523 | pbuf->port = 0; | ||
524 | |||
525 | /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ | ||
526 | memcpy(&adapter->ahw.cmd_desc_head[producer], | ||
527 | &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); | ||
528 | |||
529 | producer = get_next_index(producer, | ||
530 | adapter->max_tx_desc_count); | ||
531 | i++; | ||
532 | |||
533 | } while (i != nr_elements); | ||
534 | |||
535 | adapter->cmd_producer = producer; | ||
536 | |||
537 | /* write producer index to start the xmit */ | ||
538 | |||
539 | netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); | ||
346 | 540 | ||
347 | return 0; | 541 | return 0; |
348 | } | 542 | } |
349 | 543 | ||
350 | /* | 544 | #define NIC_REQUEST 0x14 |
351 | * check if the firmware has been downloaded and ready to run and | 545 | #define NETXEN_MAC_EVENT 0x1 |
352 | * setup the address for the descriptors in the adapter | 546 | |
353 | */ | 547 | static int nx_p3_sre_macaddr_change(struct net_device *dev, |
354 | int netxen_nic_hw_resources(struct netxen_adapter *adapter) | 548 | u8 *addr, unsigned op) |
355 | { | 549 | { |
356 | struct netxen_hardware_context *hw = &adapter->ahw; | 550 | struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv; |
357 | u32 state = 0; | 551 | nx_nic_req_t req; |
358 | void *addr; | 552 | nx_mac_req_t mac_req; |
359 | int loops = 0, err = 0; | 553 | int rv; |
360 | int ctx, ring; | 554 | |
361 | struct netxen_recv_context *recv_ctx; | 555 | memset(&req, 0, sizeof(nx_nic_req_t)); |
362 | struct netxen_rcv_desc_ctx *rcv_desc; | 556 | req.qhdr |= (NIC_REQUEST << 23); |
363 | int func_id = adapter->portnum; | 557 | req.req_hdr |= NETXEN_MAC_EVENT; |
364 | 558 | req.req_hdr |= ((u64)adapter->portnum << 16); | |
365 | DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE, | 559 | mac_req.op = op; |
366 | PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE)); | 560 | memcpy(&mac_req.mac_addr, addr, 6); |
367 | DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM, | 561 | req.words[0] = cpu_to_le64(*(u64 *)&mac_req); |
368 | pci_base_offset(adapter, NETXEN_CRB_CAM)); | 562 | |
369 | DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE, | 563 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
370 | pci_base_offset(adapter, NETXEN_CAM_RAM_BASE)); | 564 | if (rv != 0) { |
371 | 565 | printk(KERN_ERR "ERROR. Could not send mac update\n"); | |
372 | 566 | return rv; | |
373 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { | ||
374 | DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n"); | ||
375 | loops = 0; | ||
376 | state = 0; | ||
377 | /* Window 1 call */ | ||
378 | state = readl(NETXEN_CRB_NORMALIZE(adapter, | ||
379 | recv_crb_registers[ctx]. | ||
380 | crb_rcvpeg_state)); | ||
381 | while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) { | ||
382 | msleep(1); | ||
383 | /* Window 1 call */ | ||
384 | state = readl(NETXEN_CRB_NORMALIZE(adapter, | ||
385 | recv_crb_registers | ||
386 | [ctx]. | ||
387 | crb_rcvpeg_state)); | ||
388 | loops++; | ||
389 | } | ||
390 | if (loops >= 20) { | ||
391 | printk(KERN_ERR "Rcv Peg initialization not complete:" | ||
392 | "%x.\n", state); | ||
393 | err = -EIO; | ||
394 | return err; | ||
395 | } | ||
396 | } | 567 | } |
397 | adapter->intr_scheme = readl( | ||
398 | NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); | ||
399 | adapter->msi_mode = readl( | ||
400 | NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW)); | ||
401 | |||
402 | addr = netxen_alloc(adapter->ahw.pdev, | ||
403 | sizeof(struct netxen_ring_ctx) + | ||
404 | sizeof(uint32_t), | ||
405 | (dma_addr_t *) & adapter->ctx_desc_phys_addr, | ||
406 | &adapter->ctx_desc_pdev); | ||
407 | |||
408 | if (addr == NULL) { | ||
409 | DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); | ||
410 | err = -ENOMEM; | ||
411 | return err; | ||
412 | } | ||
413 | memset(addr, 0, sizeof(struct netxen_ring_ctx)); | ||
414 | adapter->ctx_desc = (struct netxen_ring_ctx *)addr; | ||
415 | adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum); | ||
416 | adapter->ctx_desc->cmd_consumer_offset = | ||
417 | cpu_to_le64(adapter->ctx_desc_phys_addr + | ||
418 | sizeof(struct netxen_ring_ctx)); | ||
419 | adapter->cmd_consumer = (__le32 *) (((char *)addr) + | ||
420 | sizeof(struct netxen_ring_ctx)); | ||
421 | |||
422 | addr = netxen_alloc(adapter->ahw.pdev, | ||
423 | sizeof(struct cmd_desc_type0) * | ||
424 | adapter->max_tx_desc_count, | ||
425 | (dma_addr_t *) & hw->cmd_desc_phys_addr, | ||
426 | &adapter->ahw.cmd_desc_pdev); | ||
427 | |||
428 | if (addr == NULL) { | ||
429 | DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); | ||
430 | netxen_free_hw_resources(adapter); | ||
431 | return -ENOMEM; | ||
432 | } | ||
433 | |||
434 | adapter->ctx_desc->cmd_ring_addr = | ||
435 | cpu_to_le64(hw->cmd_desc_phys_addr); | ||
436 | adapter->ctx_desc->cmd_ring_size = | ||
437 | cpu_to_le32(adapter->max_tx_desc_count); | ||
438 | |||
439 | hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; | ||
440 | |||
441 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { | ||
442 | recv_ctx = &adapter->recv_ctx[ctx]; | ||
443 | |||
444 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { | ||
445 | rcv_desc = &recv_ctx->rcv_desc[ring]; | ||
446 | addr = netxen_alloc(adapter->ahw.pdev, | ||
447 | RCV_DESC_RINGSIZE, | ||
448 | &rcv_desc->phys_addr, | ||
449 | &rcv_desc->phys_pdev); | ||
450 | if (addr == NULL) { | ||
451 | DPRINTK(ERR, "bad return from " | ||
452 | "pci_alloc_consistent\n"); | ||
453 | netxen_free_hw_resources(adapter); | ||
454 | err = -ENOMEM; | ||
455 | return err; | ||
456 | } | ||
457 | rcv_desc->desc_head = (struct rcv_desc *)addr; | ||
458 | adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = | ||
459 | cpu_to_le64(rcv_desc->phys_addr); | ||
460 | adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = | ||
461 | cpu_to_le32(rcv_desc->max_rx_desc_count); | ||
462 | } | ||
463 | 568 | ||
464 | addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE, | 569 | return 0; |
465 | &recv_ctx->rcv_status_desc_phys_addr, | ||
466 | &recv_ctx->rcv_status_desc_pdev); | ||
467 | if (addr == NULL) { | ||
468 | DPRINTK(ERR, "bad return from" | ||
469 | " pci_alloc_consistent\n"); | ||
470 | netxen_free_hw_resources(adapter); | ||
471 | err = -ENOMEM; | ||
472 | return err; | ||
473 | } | ||
474 | recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; | ||
475 | adapter->ctx_desc->sts_ring_addr = | ||
476 | cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); | ||
477 | adapter->ctx_desc->sts_ring_size = | ||
478 | cpu_to_le32(adapter->max_rx_desc_count); | ||
479 | |||
480 | } | ||
481 | /* Window = 1 */ | ||
482 | |||
483 | writel(lower32(adapter->ctx_desc_phys_addr), | ||
484 | NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO(func_id))); | ||
485 | writel(upper32(adapter->ctx_desc_phys_addr), | ||
486 | NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI(func_id))); | ||
487 | writel(NETXEN_CTX_SIGNATURE | func_id, | ||
488 | NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG(func_id))); | ||
489 | return err; | ||
490 | } | 570 | } |
491 | 571 | ||
492 | void netxen_free_hw_resources(struct netxen_adapter *adapter) | 572 | void netxen_p3_nic_set_multi(struct net_device *netdev) |
493 | { | 573 | { |
494 | struct netxen_recv_context *recv_ctx; | 574 | struct netxen_adapter *adapter = netdev_priv(netdev); |
495 | struct netxen_rcv_desc_ctx *rcv_desc; | 575 | nx_mac_list_t *cur, *next, *del_list, *add_list = NULL; |
496 | int ctx, ring; | 576 | struct dev_mc_list *mc_ptr; |
497 | 577 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | |
498 | if (adapter->ctx_desc != NULL) { | 578 | |
499 | pci_free_consistent(adapter->ctx_desc_pdev, | 579 | adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE); |
500 | sizeof(struct netxen_ring_ctx) + | ||
501 | sizeof(uint32_t), | ||
502 | adapter->ctx_desc, | ||
503 | adapter->ctx_desc_phys_addr); | ||
504 | adapter->ctx_desc = NULL; | ||
505 | } | ||
506 | |||
507 | if (adapter->ahw.cmd_desc_head != NULL) { | ||
508 | pci_free_consistent(adapter->ahw.cmd_desc_pdev, | ||
509 | sizeof(struct cmd_desc_type0) * | ||
510 | adapter->max_tx_desc_count, | ||
511 | adapter->ahw.cmd_desc_head, | ||
512 | adapter->ahw.cmd_desc_phys_addr); | ||
513 | adapter->ahw.cmd_desc_head = NULL; | ||
514 | } | ||
515 | |||
516 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { | ||
517 | recv_ctx = &adapter->recv_ctx[ctx]; | ||
518 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { | ||
519 | rcv_desc = &recv_ctx->rcv_desc[ring]; | ||
520 | |||
521 | if (rcv_desc->desc_head != NULL) { | ||
522 | pci_free_consistent(rcv_desc->phys_pdev, | ||
523 | RCV_DESC_RINGSIZE, | ||
524 | rcv_desc->desc_head, | ||
525 | rcv_desc->phys_addr); | ||
526 | rcv_desc->desc_head = NULL; | ||
527 | } | ||
528 | } | ||
529 | 580 | ||
530 | if (recv_ctx->rcv_status_desc_head != NULL) { | 581 | /* |
531 | pci_free_consistent(recv_ctx->rcv_status_desc_pdev, | 582 | * Programming mac addresses will automaticly enabling L2 filtering. |
532 | STATUS_DESC_RINGSIZE, | 583 | * HW will replace timestamp with L2 conid when L2 filtering is |
533 | recv_ctx->rcv_status_desc_head, | 584 | * enabled. This causes problem for LSA. Do not enabling L2 filtering |
534 | recv_ctx-> | 585 | * until that problem is fixed. |
535 | rcv_status_desc_phys_addr); | 586 | */ |
536 | recv_ctx->rcv_status_desc_head = NULL; | 587 | if ((netdev->flags & IFF_PROMISC) || |
588 | (netdev->mc_count > adapter->max_mc_count)) | ||
589 | return; | ||
590 | |||
591 | del_list = adapter->mac_list; | ||
592 | adapter->mac_list = NULL; | ||
593 | |||
594 | nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list); | ||
595 | if (netdev->mc_count > 0) { | ||
596 | nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list); | ||
597 | for (mc_ptr = netdev->mc_list; mc_ptr; | ||
598 | mc_ptr = mc_ptr->next) { | ||
599 | nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, | ||
600 | &add_list, &del_list); | ||
537 | } | 601 | } |
538 | } | 602 | } |
603 | for (cur = del_list; cur;) { | ||
604 | nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL); | ||
605 | next = cur->next; | ||
606 | kfree(cur); | ||
607 | cur = next; | ||
608 | } | ||
609 | for (cur = add_list; cur;) { | ||
610 | nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD); | ||
611 | next = cur->next; | ||
612 | cur->next = adapter->mac_list; | ||
613 | adapter->mac_list = cur; | ||
614 | cur = next; | ||
615 | } | ||
539 | } | 616 | } |
540 | 617 | ||
541 | void netxen_tso_check(struct netxen_adapter *adapter, | 618 | #define NETXEN_CONFIG_INTR_COALESCE 3 |
542 | struct cmd_desc_type0 *desc, struct sk_buff *skb) | 619 | |
620 | /* | ||
621 | * Send the interrupt coalescing parameter set by ethtool to the card. | ||
622 | */ | ||
623 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter) | ||
543 | { | 624 | { |
544 | if (desc->mss) { | 625 | nx_nic_req_t req; |
545 | desc->total_hdr_length = (sizeof(struct ethhdr) + | 626 | int rv; |
546 | ip_hdrlen(skb) + tcp_hdrlen(skb)); | 627 | |
547 | netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); | 628 | memset(&req, 0, sizeof(nx_nic_req_t)); |
548 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { | 629 | |
549 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) { | 630 | req.qhdr |= (NIC_REQUEST << 23); |
550 | netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); | 631 | req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE; |
551 | } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) { | 632 | req.req_hdr |= ((u64)adapter->portnum << 16); |
552 | netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); | 633 | |
553 | } else { | 634 | memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal)); |
554 | return; | 635 | |
555 | } | 636 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
637 | if (rv != 0) { | ||
638 | printk(KERN_ERR "ERROR. Could not send " | ||
639 | "interrupt coalescing parameters\n"); | ||
556 | } | 640 | } |
557 | desc->tcp_hdr_offset = skb_transport_offset(skb); | 641 | |
558 | desc->ip_hdr_offset = skb_network_offset(skb); | 642 | return rv; |
643 | } | ||
644 | |||
645 | /* | ||
646 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | ||
647 | * @returns 0 on success, negative on failure | ||
648 | */ | ||
649 | |||
650 | #define MTU_FUDGE_FACTOR 100 | ||
651 | |||
652 | int netxen_nic_change_mtu(struct net_device *netdev, int mtu) | ||
653 | { | ||
654 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
655 | int max_mtu; | ||
656 | |||
657 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
658 | max_mtu = P3_MAX_MTU; | ||
659 | else | ||
660 | max_mtu = P2_MAX_MTU; | ||
661 | |||
662 | if (mtu > max_mtu) { | ||
663 | printk(KERN_ERR "%s: mtu > %d bytes unsupported\n", | ||
664 | netdev->name, max_mtu); | ||
665 | return -EINVAL; | ||
666 | } | ||
667 | |||
668 | if (adapter->set_mtu) | ||
669 | adapter->set_mtu(adapter, mtu); | ||
670 | netdev->mtu = mtu; | ||
671 | |||
672 | mtu += MTU_FUDGE_FACTOR; | ||
673 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
674 | nx_fw_cmd_set_mtu(adapter, mtu); | ||
675 | else if (adapter->set_mtu) | ||
676 | adapter->set_mtu(adapter, mtu); | ||
677 | |||
678 | return 0; | ||
559 | } | 679 | } |
560 | 680 | ||
561 | int netxen_is_flash_supported(struct netxen_adapter *adapter) | 681 | int netxen_is_flash_supported(struct netxen_adapter *adapter) |
@@ -632,41 +752,49 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]) | |||
632 | return 0; | 752 | return 0; |
633 | } | 753 | } |
634 | 754 | ||
755 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | ||
756 | |||
757 | static int crb_win_lock(struct netxen_adapter *adapter) | ||
758 | { | ||
759 | int done = 0, timeout = 0; | ||
760 | |||
761 | while (!done) { | ||
762 | /* acquire semaphore3 from PCI HW block */ | ||
763 | adapter->hw_read_wx(adapter, | ||
764 | NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4); | ||
765 | if (done == 1) | ||
766 | break; | ||
767 | if (timeout >= CRB_WIN_LOCK_TIMEOUT) | ||
768 | return -1; | ||
769 | timeout++; | ||
770 | udelay(1); | ||
771 | } | ||
772 | netxen_crb_writelit_adapter(adapter, | ||
773 | NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static void crb_win_unlock(struct netxen_adapter *adapter) | ||
778 | { | ||
779 | int val; | ||
780 | |||
781 | adapter->hw_read_wx(adapter, | ||
782 | NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4); | ||
783 | } | ||
784 | |||
635 | /* | 785 | /* |
636 | * Changes the CRB window to the specified window. | 786 | * Changes the CRB window to the specified window. |
637 | */ | 787 | */ |
638 | void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) | 788 | void |
789 | netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) | ||
639 | { | 790 | { |
640 | void __iomem *offset; | 791 | void __iomem *offset; |
641 | u32 tmp; | 792 | u32 tmp; |
642 | int count = 0; | 793 | int count = 0; |
794 | uint8_t func = adapter->ahw.pci_func; | ||
643 | 795 | ||
644 | if (adapter->curr_window == wndw) | 796 | if (adapter->curr_window == wndw) |
645 | return; | 797 | return; |
646 | switch(adapter->ahw.pci_func) { | ||
647 | case 0: | ||
648 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
649 | NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW)); | ||
650 | break; | ||
651 | case 1: | ||
652 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
653 | NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F1)); | ||
654 | break; | ||
655 | case 2: | ||
656 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
657 | NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F2)); | ||
658 | break; | ||
659 | case 3: | ||
660 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
661 | NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F3)); | ||
662 | break; | ||
663 | default: | ||
664 | printk(KERN_INFO "Changing the window for PCI function " | ||
665 | "%d\n", adapter->ahw.pci_func); | ||
666 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
667 | NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW)); | ||
668 | break; | ||
669 | } | ||
670 | /* | 798 | /* |
671 | * Move the CRB window. | 799 | * Move the CRB window. |
672 | * We need to write to the "direct access" region of PCI | 800 | * We need to write to the "direct access" region of PCI |
@@ -675,6 +803,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) | |||
675 | * register address is received by PCI. The direct region bypasses | 803 | * register address is received by PCI. The direct region bypasses |
676 | * the CRB bus. | 804 | * the CRB bus. |
677 | */ | 805 | */ |
806 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
807 | NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func))); | ||
678 | 808 | ||
679 | if (wndw & 0x1) | 809 | if (wndw & 0x1) |
680 | wndw = NETXEN_WINDOW_ONE; | 810 | wndw = NETXEN_WINDOW_ONE; |
@@ -685,7 +815,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) | |||
685 | while ((tmp = readl(offset)) != wndw) { | 815 | while ((tmp = readl(offset)) != wndw) { |
686 | printk(KERN_WARNING "%s: %s WARNING: CRB window value not " | 816 | printk(KERN_WARNING "%s: %s WARNING: CRB window value not " |
687 | "registered properly: 0x%08x.\n", | 817 | "registered properly: 0x%08x.\n", |
688 | netxen_nic_driver_name, __FUNCTION__, tmp); | 818 | netxen_nic_driver_name, __func__, tmp); |
689 | mdelay(1); | 819 | mdelay(1); |
690 | if (count >= 10) | 820 | if (count >= 10) |
691 | break; | 821 | break; |
@@ -698,51 +828,119 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) | |||
698 | adapter->curr_window = 0; | 828 | adapter->curr_window = 0; |
699 | } | 829 | } |
700 | 830 | ||
831 | /* | ||
832 | * Return -1 if off is not valid, | ||
833 | * 1 if window access is needed. 'off' is set to offset from | ||
834 | * CRB space in 128M pci map | ||
835 | * 0 if no window access is needed. 'off' is set to 2M addr | ||
836 | * In: 'off' is offset from base in 128M pci map | ||
837 | */ | ||
838 | static int | ||
839 | netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, | ||
840 | ulong *off, int len) | ||
841 | { | ||
842 | unsigned long end = *off + len; | ||
843 | crb_128M_2M_sub_block_map_t *m; | ||
844 | |||
845 | |||
846 | if (*off >= NETXEN_CRB_MAX) | ||
847 | return -1; | ||
848 | |||
849 | if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) { | ||
850 | *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + | ||
851 | (ulong)adapter->ahw.pci_base0; | ||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | if (*off < NETXEN_PCI_CRBSPACE) | ||
856 | return -1; | ||
857 | |||
858 | *off -= NETXEN_PCI_CRBSPACE; | ||
859 | end = *off + len; | ||
860 | |||
861 | /* | ||
862 | * Try direct map | ||
863 | */ | ||
864 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | ||
865 | |||
866 | if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) { | ||
867 | *off = *off + m->start_2M - m->start_128M + | ||
868 | (ulong)adapter->ahw.pci_base0; | ||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Not in direct map, use crb window | ||
874 | */ | ||
875 | return 1; | ||
876 | } | ||
877 | |||
878 | /* | ||
879 | * In: 'off' is offset from CRB space in 128M pci map | ||
880 | * Out: 'off' is 2M pci map addr | ||
881 | * side effect: lock crb window | ||
882 | */ | ||
883 | static void | ||
884 | netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) | ||
885 | { | ||
886 | u32 win_read; | ||
887 | |||
888 | adapter->crb_win = CRB_HI(*off); | ||
889 | writel(adapter->crb_win, (void *)(CRB_WINDOW_2M + | ||
890 | adapter->ahw.pci_base0)); | ||
891 | /* | ||
892 | * Read back value to make sure write has gone through before trying | ||
893 | * to use it. | ||
894 | */ | ||
895 | win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0)); | ||
896 | if (win_read != adapter->crb_win) { | ||
897 | printk(KERN_ERR "%s: Written crbwin (0x%x) != " | ||
898 | "Read crbwin (0x%x), off=0x%lx\n", | ||
899 | __func__, adapter->crb_win, win_read, *off); | ||
900 | } | ||
901 | *off = (*off & MASK(16)) + CRB_INDIRECT_2M + | ||
902 | (ulong)adapter->ahw.pci_base0; | ||
903 | } | ||
904 | |||
701 | int netxen_load_firmware(struct netxen_adapter *adapter) | 905 | int netxen_load_firmware(struct netxen_adapter *adapter) |
702 | { | 906 | { |
703 | int i; | 907 | int i; |
704 | u32 data, size = 0; | 908 | u32 data, size = 0; |
705 | u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE; | 909 | u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START; |
706 | u64 off; | ||
707 | void __iomem *addr; | ||
708 | 910 | ||
709 | size = NETXEN_FIRMWARE_LEN; | 911 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; |
710 | writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); | 912 | |
913 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
914 | adapter->pci_write_normalize(adapter, | ||
915 | NETXEN_ROMUSB_GLB_CAS_RST, 1); | ||
711 | 916 | ||
712 | for (i = 0; i < size; i++) { | 917 | for (i = 0; i < size; i++) { |
713 | int retries = 10; | ||
714 | if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) | 918 | if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) |
715 | return -EIO; | 919 | return -EIO; |
716 | 920 | ||
717 | off = netxen_nic_pci_set_window(adapter, memaddr); | 921 | adapter->pci_mem_write(adapter, memaddr, &data, 4); |
718 | addr = pci_base_offset(adapter, off); | ||
719 | writel(data, addr); | ||
720 | do { | ||
721 | if (readl(addr) == data) | ||
722 | break; | ||
723 | msleep(100); | ||
724 | writel(data, addr); | ||
725 | } while (--retries); | ||
726 | if (!retries) { | ||
727 | printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n", | ||
728 | netxen_nic_driver_name, memaddr); | ||
729 | return -EIO; | ||
730 | } | ||
731 | flashaddr += 4; | 922 | flashaddr += 4; |
732 | memaddr += 4; | 923 | memaddr += 4; |
924 | cond_resched(); | ||
925 | } | ||
926 | msleep(1); | ||
927 | |||
928 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
929 | adapter->pci_write_normalize(adapter, | ||
930 | NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); | ||
931 | else { | ||
932 | adapter->pci_write_normalize(adapter, | ||
933 | NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); | ||
934 | adapter->pci_write_normalize(adapter, | ||
935 | NETXEN_ROMUSB_GLB_CAS_RST, 0); | ||
733 | } | 936 | } |
734 | udelay(100); | ||
735 | /* make sure Casper is powered on */ | ||
736 | writel(0x3fff, | ||
737 | NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL)); | ||
738 | writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); | ||
739 | 937 | ||
740 | return 0; | 938 | return 0; |
741 | } | 939 | } |
742 | 940 | ||
743 | int | 941 | int |
744 | netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, | 942 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, |
745 | int len) | 943 | ulong off, void *data, int len) |
746 | { | 944 | { |
747 | void __iomem *addr; | 945 | void __iomem *addr; |
748 | 946 | ||
@@ -750,7 +948,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, | |||
750 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | 948 | addr = NETXEN_CRB_NORMALIZE(adapter, off); |
751 | } else { /* Window 0 */ | 949 | } else { /* Window 0 */ |
752 | addr = pci_base_offset(adapter, off); | 950 | addr = pci_base_offset(adapter, off); |
753 | netxen_nic_pci_change_crbwindow(adapter, 0); | 951 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); |
754 | } | 952 | } |
755 | 953 | ||
756 | DPRINTK(INFO, "writing to base %lx offset %llx addr %p" | 954 | DPRINTK(INFO, "writing to base %lx offset %llx addr %p" |
@@ -758,7 +956,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, | |||
758 | pci_base(adapter, off), off, addr, | 956 | pci_base(adapter, off), off, addr, |
759 | *(unsigned long long *)data, len); | 957 | *(unsigned long long *)data, len); |
760 | if (!addr) { | 958 | if (!addr) { |
761 | netxen_nic_pci_change_crbwindow(adapter, 1); | 959 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); |
762 | return 1; | 960 | return 1; |
763 | } | 961 | } |
764 | 962 | ||
@@ -785,14 +983,14 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, | |||
785 | break; | 983 | break; |
786 | } | 984 | } |
787 | if (!ADDR_IN_WINDOW1(off)) | 985 | if (!ADDR_IN_WINDOW1(off)) |
788 | netxen_nic_pci_change_crbwindow(adapter, 1); | 986 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); |
789 | 987 | ||
790 | return 0; | 988 | return 0; |
791 | } | 989 | } |
792 | 990 | ||
793 | int | 991 | int |
794 | netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, | 992 | netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, |
795 | int len) | 993 | ulong off, void *data, int len) |
796 | { | 994 | { |
797 | void __iomem *addr; | 995 | void __iomem *addr; |
798 | 996 | ||
@@ -800,13 +998,13 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, | |||
800 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | 998 | addr = NETXEN_CRB_NORMALIZE(adapter, off); |
801 | } else { /* Window 0 */ | 999 | } else { /* Window 0 */ |
802 | addr = pci_base_offset(adapter, off); | 1000 | addr = pci_base_offset(adapter, off); |
803 | netxen_nic_pci_change_crbwindow(adapter, 0); | 1001 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); |
804 | } | 1002 | } |
805 | 1003 | ||
806 | DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", | 1004 | DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", |
807 | pci_base(adapter, off), off, addr); | 1005 | pci_base(adapter, off), off, addr); |
808 | if (!addr) { | 1006 | if (!addr) { |
809 | netxen_nic_pci_change_crbwindow(adapter, 1); | 1007 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); |
810 | return 1; | 1008 | return 1; |
811 | } | 1009 | } |
812 | switch (len) { | 1010 | switch (len) { |
@@ -830,81 +1028,195 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, | |||
830 | DPRINTK(INFO, "read %lx\n", *(unsigned long *)data); | 1028 | DPRINTK(INFO, "read %lx\n", *(unsigned long *)data); |
831 | 1029 | ||
832 | if (!ADDR_IN_WINDOW1(off)) | 1030 | if (!ADDR_IN_WINDOW1(off)) |
833 | netxen_nic_pci_change_crbwindow(adapter, 1); | 1031 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); |
834 | 1032 | ||
835 | return 0; | 1033 | return 0; |
836 | } | 1034 | } |
837 | 1035 | ||
838 | void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) | 1036 | int |
839 | { /* Only for window 1 */ | 1037 | netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, |
840 | void __iomem *addr; | 1038 | ulong off, void *data, int len) |
1039 | { | ||
1040 | unsigned long flags = 0; | ||
1041 | int rv; | ||
1042 | |||
1043 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); | ||
1044 | |||
1045 | if (rv == -1) { | ||
1046 | printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", | ||
1047 | __func__, off); | ||
1048 | dump_stack(); | ||
1049 | return -1; | ||
1050 | } | ||
1051 | |||
1052 | if (rv == 1) { | ||
1053 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1054 | crb_win_lock(adapter); | ||
1055 | netxen_nic_pci_set_crbwindow_2M(adapter, &off); | ||
1056 | } | ||
841 | 1057 | ||
842 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | 1058 | DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n", |
843 | DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n", | 1059 | *(unsigned long *)data, off, len); |
844 | pci_base(adapter, off), off, addr, val); | ||
845 | writel(val, addr); | ||
846 | 1060 | ||
1061 | switch (len) { | ||
1062 | case 1: | ||
1063 | writeb(*(uint8_t *)data, (void *)off); | ||
1064 | break; | ||
1065 | case 2: | ||
1066 | writew(*(uint16_t *)data, (void *)off); | ||
1067 | break; | ||
1068 | case 4: | ||
1069 | writel(*(uint32_t *)data, (void *)off); | ||
1070 | break; | ||
1071 | case 8: | ||
1072 | writeq(*(uint64_t *)data, (void *)off); | ||
1073 | break; | ||
1074 | default: | ||
1075 | DPRINTK(1, INFO, | ||
1076 | "writing data %lx to offset %llx, num words=%d\n", | ||
1077 | *(unsigned long *)data, off, (len>>3)); | ||
1078 | break; | ||
1079 | } | ||
1080 | if (rv == 1) { | ||
1081 | crb_win_unlock(adapter); | ||
1082 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
847 | } | 1086 | } |
848 | 1087 | ||
849 | int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) | 1088 | int |
850 | { /* Only for window 1 */ | 1089 | netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, |
851 | void __iomem *addr; | 1090 | ulong off, void *data, int len) |
852 | int val; | 1091 | { |
1092 | unsigned long flags = 0; | ||
1093 | int rv; | ||
853 | 1094 | ||
854 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | 1095 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); |
855 | DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", | 1096 | |
856 | pci_base(adapter, off), off, addr); | 1097 | if (rv == -1) { |
857 | val = readl(addr); | 1098 | printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", |
858 | writel(val, addr); | 1099 | __func__, off); |
1100 | dump_stack(); | ||
1101 | return -1; | ||
1102 | } | ||
1103 | |||
1104 | if (rv == 1) { | ||
1105 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1106 | crb_win_lock(adapter); | ||
1107 | netxen_nic_pci_set_crbwindow_2M(adapter, &off); | ||
1108 | } | ||
1109 | |||
1110 | DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len); | ||
1111 | |||
1112 | switch (len) { | ||
1113 | case 1: | ||
1114 | *(uint8_t *)data = readb((void *)off); | ||
1115 | break; | ||
1116 | case 2: | ||
1117 | *(uint16_t *)data = readw((void *)off); | ||
1118 | break; | ||
1119 | case 4: | ||
1120 | *(uint32_t *)data = readl((void *)off); | ||
1121 | break; | ||
1122 | case 8: | ||
1123 | *(uint64_t *)data = readq((void *)off); | ||
1124 | break; | ||
1125 | default: | ||
1126 | break; | ||
1127 | } | ||
859 | 1128 | ||
1129 | DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data); | ||
1130 | |||
1131 | if (rv == 1) { | ||
1132 | crb_win_unlock(adapter); | ||
1133 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1134 | } | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) | ||
1140 | { | ||
1141 | adapter->hw_write_wx(adapter, off, &val, 4); | ||
1142 | } | ||
1143 | |||
1144 | int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) | ||
1145 | { | ||
1146 | int val; | ||
1147 | adapter->hw_read_wx(adapter, off, &val, 4); | ||
860 | return val; | 1148 | return val; |
861 | } | 1149 | } |
862 | 1150 | ||
863 | /* Change the window to 0, write and change back to window 1. */ | 1151 | /* Change the window to 0, write and change back to window 1. */ |
864 | void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) | 1152 | void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) |
865 | { | 1153 | { |
866 | void __iomem *addr; | 1154 | adapter->hw_write_wx(adapter, index, &value, 4); |
867 | |||
868 | netxen_nic_pci_change_crbwindow(adapter, 0); | ||
869 | addr = pci_base_offset(adapter, index); | ||
870 | writel(value, addr); | ||
871 | netxen_nic_pci_change_crbwindow(adapter, 1); | ||
872 | } | 1155 | } |
873 | 1156 | ||
874 | /* Change the window to 0, read and change back to window 1. */ | 1157 | /* Change the window to 0, read and change back to window 1. */ |
875 | void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value) | 1158 | void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value) |
876 | { | 1159 | { |
877 | void __iomem *addr; | 1160 | adapter->hw_read_wx(adapter, index, value, 4); |
1161 | } | ||
878 | 1162 | ||
879 | addr = pci_base_offset(adapter, index); | 1163 | void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value) |
1164 | { | ||
1165 | adapter->hw_write_wx(adapter, index, &value, 4); | ||
1166 | } | ||
1167 | |||
1168 | void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value) | ||
1169 | { | ||
1170 | adapter->hw_read_wx(adapter, index, value, 4); | ||
1171 | } | ||
1172 | |||
1173 | /* | ||
1174 | * check memory access boundary. | ||
1175 | * used by test agent. support ddr access only for now | ||
1176 | */ | ||
1177 | static unsigned long | ||
1178 | netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter, | ||
1179 | unsigned long long addr, int size) | ||
1180 | { | ||
1181 | if (!ADDR_IN_RANGE(addr, | ||
1182 | NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) || | ||
1183 | !ADDR_IN_RANGE(addr+size-1, | ||
1184 | NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) || | ||
1185 | ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { | ||
1186 | return 0; | ||
1187 | } | ||
880 | 1188 | ||
881 | netxen_nic_pci_change_crbwindow(adapter, 0); | 1189 | return 1; |
882 | *value = readl(addr); | ||
883 | netxen_nic_pci_change_crbwindow(adapter, 1); | ||
884 | } | 1190 | } |
885 | 1191 | ||
886 | static int netxen_pci_set_window_warning_count; | 1192 | static int netxen_pci_set_window_warning_count; |
887 | 1193 | ||
888 | static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter, | 1194 | unsigned long |
889 | unsigned long long addr) | 1195 | netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, |
1196 | unsigned long long addr) | ||
890 | { | 1197 | { |
891 | static int ddr_mn_window = -1; | 1198 | void __iomem *offset; |
892 | static int qdr_sn_window = -1; | ||
893 | int window; | 1199 | int window; |
1200 | unsigned long long qdr_max; | ||
1201 | uint8_t func = adapter->ahw.pci_func; | ||
1202 | |||
1203 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1204 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2; | ||
1205 | } else { | ||
1206 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3; | ||
1207 | } | ||
894 | 1208 | ||
895 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1209 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { |
896 | /* DDR network side */ | 1210 | /* DDR network side */ |
897 | addr -= NETXEN_ADDR_DDR_NET; | 1211 | addr -= NETXEN_ADDR_DDR_NET; |
898 | window = (addr >> 25) & 0x3ff; | 1212 | window = (addr >> 25) & 0x3ff; |
899 | if (ddr_mn_window != window) { | 1213 | if (adapter->ahw.ddr_mn_window != window) { |
900 | ddr_mn_window = window; | 1214 | adapter->ahw.ddr_mn_window = window; |
901 | writel(window, PCI_OFFSET_SECOND_RANGE(adapter, | 1215 | offset = PCI_OFFSET_SECOND_RANGE(adapter, |
902 | NETXEN_PCIX_PH_REG | 1216 | NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func))); |
903 | (PCIX_MN_WINDOW(adapter->ahw.pci_func)))); | 1217 | writel(window, offset); |
904 | /* MUST make sure window is set before we forge on... */ | 1218 | /* MUST make sure window is set before we forge on... */ |
905 | readl(PCI_OFFSET_SECOND_RANGE(adapter, | 1219 | readl(offset); |
906 | NETXEN_PCIX_PH_REG | ||
907 | (PCIX_MN_WINDOW(adapter->ahw.pci_func)))); | ||
908 | } | 1220 | } |
909 | addr -= (window * NETXEN_WINDOW_ONE); | 1221 | addr -= (window * NETXEN_WINDOW_ONE); |
910 | addr += NETXEN_PCI_DDR_NET; | 1222 | addr += NETXEN_PCI_DDR_NET; |
@@ -914,22 +1226,17 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter, | |||
914 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | 1226 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { |
915 | addr -= NETXEN_ADDR_OCM1; | 1227 | addr -= NETXEN_ADDR_OCM1; |
916 | addr += NETXEN_PCI_OCM1; | 1228 | addr += NETXEN_PCI_OCM1; |
917 | } else | 1229 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) { |
918 | if (ADDR_IN_RANGE | ||
919 | (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) { | ||
920 | /* QDR network side */ | 1230 | /* QDR network side */ |
921 | addr -= NETXEN_ADDR_QDR_NET; | 1231 | addr -= NETXEN_ADDR_QDR_NET; |
922 | window = (addr >> 22) & 0x3f; | 1232 | window = (addr >> 22) & 0x3f; |
923 | if (qdr_sn_window != window) { | 1233 | if (adapter->ahw.qdr_sn_window != window) { |
924 | qdr_sn_window = window; | 1234 | adapter->ahw.qdr_sn_window = window; |
925 | writel((window << 22), | 1235 | offset = PCI_OFFSET_SECOND_RANGE(adapter, |
926 | PCI_OFFSET_SECOND_RANGE(adapter, | 1236 | NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func))); |
927 | NETXEN_PCIX_PH_REG | 1237 | writel((window << 22), offset); |
928 | (PCIX_SN_WINDOW(adapter->ahw.pci_func)))); | ||
929 | /* MUST make sure window is set before we forge on... */ | 1238 | /* MUST make sure window is set before we forge on... */ |
930 | readl(PCI_OFFSET_SECOND_RANGE(adapter, | 1239 | readl(offset); |
931 | NETXEN_PCIX_PH_REG | ||
932 | (PCIX_SN_WINDOW(adapter->ahw.pci_func)))); | ||
933 | } | 1240 | } |
934 | addr -= (window * 0x400000); | 1241 | addr -= (window * 0x400000); |
935 | addr += NETXEN_PCI_QDR_NET; | 1242 | addr += NETXEN_PCI_QDR_NET; |
@@ -943,11 +1250,711 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter, | |||
943 | printk("%s: Warning:netxen_nic_pci_set_window()" | 1250 | printk("%s: Warning:netxen_nic_pci_set_window()" |
944 | " Unknown address range!\n", | 1251 | " Unknown address range!\n", |
945 | netxen_nic_driver_name); | 1252 | netxen_nic_driver_name); |
1253 | addr = -1UL; | ||
1254 | } | ||
1255 | return addr; | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | * Note : only 32-bit writes! | ||
1260 | */ | ||
1261 | int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter, | ||
1262 | u64 off, u32 data) | ||
1263 | { | ||
1264 | writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off))); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off) | ||
1269 | { | ||
1270 | return readl((void __iomem *)(pci_base_offset(adapter, off))); | ||
1271 | } | ||
1272 | |||
1273 | void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter, | ||
1274 | u64 off, u32 data) | ||
1275 | { | ||
1276 | writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); | ||
1277 | } | ||
1278 | |||
1279 | u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off) | ||
1280 | { | ||
1281 | return readl(NETXEN_CRB_NORMALIZE(adapter, off)); | ||
1282 | } | ||
1283 | |||
1284 | unsigned long | ||
1285 | netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, | ||
1286 | unsigned long long addr) | ||
1287 | { | ||
1288 | int window; | ||
1289 | u32 win_read; | ||
1290 | |||
1291 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1292 | /* DDR network side */ | ||
1293 | window = MN_WIN(addr); | ||
1294 | adapter->ahw.ddr_mn_window = window; | ||
1295 | adapter->hw_write_wx(adapter, | ||
1296 | adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, | ||
1297 | &window, 4); | ||
1298 | adapter->hw_read_wx(adapter, | ||
1299 | adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, | ||
1300 | &win_read, 4); | ||
1301 | if ((win_read << 17) != window) { | ||
1302 | printk(KERN_INFO "Written MNwin (0x%x) != " | ||
1303 | "Read MNwin (0x%x)\n", window, win_read); | ||
1304 | } | ||
1305 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET; | ||
1306 | } else if (ADDR_IN_RANGE(addr, | ||
1307 | NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1308 | if ((addr & 0x00ff800) == 0xff800) { | ||
1309 | printk("%s: QM access not handled.\n", __func__); | ||
1310 | addr = -1UL; | ||
1311 | } | ||
1312 | |||
1313 | window = OCM_WIN(addr); | ||
1314 | adapter->ahw.ddr_mn_window = window; | ||
1315 | adapter->hw_write_wx(adapter, | ||
1316 | adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, | ||
1317 | &window, 4); | ||
1318 | adapter->hw_read_wx(adapter, | ||
1319 | adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, | ||
1320 | &win_read, 4); | ||
1321 | if ((win_read >> 7) != window) { | ||
1322 | printk(KERN_INFO "%s: Written OCMwin (0x%x) != " | ||
1323 | "Read OCMwin (0x%x)\n", | ||
1324 | __func__, window, win_read); | ||
1325 | } | ||
1326 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M; | ||
1327 | |||
1328 | } else if (ADDR_IN_RANGE(addr, | ||
1329 | NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) { | ||
1330 | /* QDR network side */ | ||
1331 | window = MS_WIN(addr); | ||
1332 | adapter->ahw.qdr_sn_window = window; | ||
1333 | adapter->hw_write_wx(adapter, | ||
1334 | adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, | ||
1335 | &window, 4); | ||
1336 | adapter->hw_read_wx(adapter, | ||
1337 | adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, | ||
1338 | &win_read, 4); | ||
1339 | if (win_read != window) { | ||
1340 | printk(KERN_INFO "%s: Written MSwin (0x%x) != " | ||
1341 | "Read MSwin (0x%x)\n", | ||
1342 | __func__, window, win_read); | ||
1343 | } | ||
1344 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET; | ||
946 | 1345 | ||
1346 | } else { | ||
1347 | /* | ||
1348 | * peg gdb frequently accesses memory that doesn't exist, | ||
1349 | * this limits the chit chat so debugging isn't slowed down. | ||
1350 | */ | ||
1351 | if ((netxen_pci_set_window_warning_count++ < 8) | ||
1352 | || (netxen_pci_set_window_warning_count%64 == 0)) { | ||
1353 | printk("%s: Warning:%s Unknown address range!\n", | ||
1354 | __func__, netxen_nic_driver_name); | ||
1355 | } | ||
1356 | addr = -1UL; | ||
947 | } | 1357 | } |
948 | return addr; | 1358 | return addr; |
949 | } | 1359 | } |
950 | 1360 | ||
1361 | static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter, | ||
1362 | unsigned long long addr) | ||
1363 | { | ||
1364 | int window; | ||
1365 | unsigned long long qdr_max; | ||
1366 | |||
1367 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1368 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2; | ||
1369 | else | ||
1370 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3; | ||
1371 | |||
1372 | if (ADDR_IN_RANGE(addr, | ||
1373 | NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1374 | /* DDR network side */ | ||
1375 | BUG(); /* MN access can not come here */ | ||
1376 | } else if (ADDR_IN_RANGE(addr, | ||
1377 | NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1378 | return 1; | ||
1379 | } else if (ADDR_IN_RANGE(addr, | ||
1380 | NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1381 | return 1; | ||
1382 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) { | ||
1383 | /* QDR network side */ | ||
1384 | window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f; | ||
1385 | if (adapter->ahw.qdr_sn_window == window) | ||
1386 | return 1; | ||
1387 | } | ||
1388 | |||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter, | ||
1393 | u64 off, void *data, int size) | ||
1394 | { | ||
1395 | unsigned long flags; | ||
1396 | void *addr; | ||
1397 | int ret = 0; | ||
1398 | u64 start; | ||
1399 | uint8_t *mem_ptr = NULL; | ||
1400 | unsigned long mem_base; | ||
1401 | unsigned long mem_page; | ||
1402 | |||
1403 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1404 | |||
1405 | /* | ||
1406 | * If attempting to access unknown address or straddle hw windows, | ||
1407 | * do not access. | ||
1408 | */ | ||
1409 | start = adapter->pci_set_window(adapter, off); | ||
1410 | if ((start == -1UL) || | ||
1411 | (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) { | ||
1412 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1413 | printk(KERN_ERR "%s out of bound pci memory access. " | ||
1414 | "offset is 0x%llx\n", netxen_nic_driver_name, off); | ||
1415 | return -1; | ||
1416 | } | ||
1417 | |||
1418 | addr = (void *)(pci_base_offset(adapter, start)); | ||
1419 | if (!addr) { | ||
1420 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1421 | mem_base = pci_resource_start(adapter->pdev, 0); | ||
1422 | mem_page = start & PAGE_MASK; | ||
1423 | /* Map two pages whenever user tries to access addresses in two | ||
1424 | consecutive pages. | ||
1425 | */ | ||
1426 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
1427 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); | ||
1428 | else | ||
1429 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
1430 | if (mem_ptr == 0UL) { | ||
1431 | *(uint8_t *)data = 0; | ||
1432 | return -1; | ||
1433 | } | ||
1434 | addr = mem_ptr; | ||
1435 | addr += start & (PAGE_SIZE - 1); | ||
1436 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1437 | } | ||
1438 | |||
1439 | switch (size) { | ||
1440 | case 1: | ||
1441 | *(uint8_t *)data = readb(addr); | ||
1442 | break; | ||
1443 | case 2: | ||
1444 | *(uint16_t *)data = readw(addr); | ||
1445 | break; | ||
1446 | case 4: | ||
1447 | *(uint32_t *)data = readl(addr); | ||
1448 | break; | ||
1449 | case 8: | ||
1450 | *(uint64_t *)data = readq(addr); | ||
1451 | break; | ||
1452 | default: | ||
1453 | ret = -1; | ||
1454 | break; | ||
1455 | } | ||
1456 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1457 | DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); | ||
1458 | |||
1459 | if (mem_ptr) | ||
1460 | iounmap(mem_ptr); | ||
1461 | return ret; | ||
1462 | } | ||
1463 | |||
1464 | static int | ||
1465 | netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off, | ||
1466 | void *data, int size) | ||
1467 | { | ||
1468 | unsigned long flags; | ||
1469 | void *addr; | ||
1470 | int ret = 0; | ||
1471 | u64 start; | ||
1472 | uint8_t *mem_ptr = NULL; | ||
1473 | unsigned long mem_base; | ||
1474 | unsigned long mem_page; | ||
1475 | |||
1476 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1477 | |||
1478 | /* | ||
1479 | * If attempting to access unknown address or straddle hw windows, | ||
1480 | * do not access. | ||
1481 | */ | ||
1482 | start = adapter->pci_set_window(adapter, off); | ||
1483 | if ((start == -1UL) || | ||
1484 | (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) { | ||
1485 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1486 | printk(KERN_ERR "%s out of bound pci memory access. " | ||
1487 | "offset is 0x%llx\n", netxen_nic_driver_name, off); | ||
1488 | return -1; | ||
1489 | } | ||
1490 | |||
1491 | addr = (void *)(pci_base_offset(adapter, start)); | ||
1492 | if (!addr) { | ||
1493 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1494 | mem_base = pci_resource_start(adapter->pdev, 0); | ||
1495 | mem_page = start & PAGE_MASK; | ||
1496 | /* Map two pages whenever user tries to access addresses in two | ||
1497 | * consecutive pages. | ||
1498 | */ | ||
1499 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
1500 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); | ||
1501 | else | ||
1502 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
1503 | if (mem_ptr == 0UL) | ||
1504 | return -1; | ||
1505 | addr = mem_ptr; | ||
1506 | addr += start & (PAGE_SIZE - 1); | ||
1507 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1508 | } | ||
1509 | |||
1510 | switch (size) { | ||
1511 | case 1: | ||
1512 | writeb(*(uint8_t *)data, addr); | ||
1513 | break; | ||
1514 | case 2: | ||
1515 | writew(*(uint16_t *)data, addr); | ||
1516 | break; | ||
1517 | case 4: | ||
1518 | writel(*(uint32_t *)data, addr); | ||
1519 | break; | ||
1520 | case 8: | ||
1521 | writeq(*(uint64_t *)data, addr); | ||
1522 | break; | ||
1523 | default: | ||
1524 | ret = -1; | ||
1525 | break; | ||
1526 | } | ||
1527 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1528 | DPRINTK(1, INFO, "writing data %llx to offset %llx\n", | ||
1529 | *(unsigned long long *)data, start); | ||
1530 | if (mem_ptr) | ||
1531 | iounmap(mem_ptr); | ||
1532 | return ret; | ||
1533 | } | ||
1534 | |||
1535 | #define MAX_CTL_CHECK 1000 | ||
1536 | |||
1537 | int | ||
1538 | netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, | ||
1539 | u64 off, void *data, int size) | ||
1540 | { | ||
1541 | unsigned long flags, mem_crb; | ||
1542 | int i, j, ret = 0, loop, sz[2], off0; | ||
1543 | uint32_t temp; | ||
1544 | uint64_t off8, tmpw, word[2] = {0, 0}; | ||
1545 | |||
1546 | /* | ||
1547 | * If not MN, go check for MS or invalid. | ||
1548 | */ | ||
1549 | if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) | ||
1550 | return netxen_nic_pci_mem_write_direct(adapter, | ||
1551 | off, data, size); | ||
1552 | |||
1553 | off8 = off & 0xfffffff8; | ||
1554 | off0 = off & 0x7; | ||
1555 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1556 | sz[1] = size - sz[0]; | ||
1557 | loop = ((off0 + size - 1) >> 3) + 1; | ||
1558 | mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET); | ||
1559 | |||
1560 | if ((size != 8) || (off0 != 0)) { | ||
1561 | for (i = 0; i < loop; i++) { | ||
1562 | if (adapter->pci_mem_read(adapter, | ||
1563 | off8 + (i << 3), &word[i], 8)) | ||
1564 | return -1; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | switch (size) { | ||
1569 | case 1: | ||
1570 | tmpw = *((uint8_t *)data); | ||
1571 | break; | ||
1572 | case 2: | ||
1573 | tmpw = *((uint16_t *)data); | ||
1574 | break; | ||
1575 | case 4: | ||
1576 | tmpw = *((uint32_t *)data); | ||
1577 | break; | ||
1578 | case 8: | ||
1579 | default: | ||
1580 | tmpw = *((uint64_t *)data); | ||
1581 | break; | ||
1582 | } | ||
1583 | word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1584 | word[0] |= tmpw << (off0 * 8); | ||
1585 | |||
1586 | if (loop == 2) { | ||
1587 | word[1] &= ~(~0ULL << (sz[1] * 8)); | ||
1588 | word[1] |= tmpw >> (sz[0] * 8); | ||
1589 | } | ||
1590 | |||
1591 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1592 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1593 | |||
1594 | for (i = 0; i < loop; i++) { | ||
1595 | writel((uint32_t)(off8 + (i << 3)), | ||
1596 | (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO)); | ||
1597 | writel(0, | ||
1598 | (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI)); | ||
1599 | writel(word[i] & 0xffffffff, | ||
1600 | (void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO)); | ||
1601 | writel((word[i] >> 32) & 0xffffffff, | ||
1602 | (void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI)); | ||
1603 | writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, | ||
1604 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1605 | writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, | ||
1606 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1607 | |||
1608 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1609 | temp = readl( | ||
1610 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1611 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1612 | break; | ||
1613 | } | ||
1614 | |||
1615 | if (j >= MAX_CTL_CHECK) { | ||
1616 | printk("%s: %s Fail to write through agent\n", | ||
1617 | __func__, netxen_nic_driver_name); | ||
1618 | ret = -1; | ||
1619 | break; | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1623 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1624 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1625 | return ret; | ||
1626 | } | ||
1627 | |||
1628 | int | ||
1629 | netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, | ||
1630 | u64 off, void *data, int size) | ||
1631 | { | ||
1632 | unsigned long flags, mem_crb; | ||
1633 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | ||
1634 | uint32_t temp; | ||
1635 | uint64_t off8, val, word[2] = {0, 0}; | ||
1636 | |||
1637 | |||
1638 | /* | ||
1639 | * If not MN, go check for MS or invalid. | ||
1640 | */ | ||
1641 | if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) | ||
1642 | return netxen_nic_pci_mem_read_direct(adapter, off, data, size); | ||
1643 | |||
1644 | off8 = off & 0xfffffff8; | ||
1645 | off0[0] = off & 0x7; | ||
1646 | off0[1] = 0; | ||
1647 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
1648 | sz[1] = size - sz[0]; | ||
1649 | loop = ((off0[0] + size - 1) >> 3) + 1; | ||
1650 | mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET); | ||
1651 | |||
1652 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1653 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1654 | |||
1655 | for (i = 0; i < loop; i++) { | ||
1656 | writel((uint32_t)(off8 + (i << 3)), | ||
1657 | (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO)); | ||
1658 | writel(0, | ||
1659 | (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI)); | ||
1660 | writel(MIU_TA_CTL_ENABLE, | ||
1661 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1662 | writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE, | ||
1663 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1664 | |||
1665 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1666 | temp = readl( | ||
1667 | (void *)(mem_crb+MIU_TEST_AGT_CTRL)); | ||
1668 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1669 | break; | ||
1670 | } | ||
1671 | |||
1672 | if (j >= MAX_CTL_CHECK) { | ||
1673 | printk(KERN_ERR "%s: %s Fail to read through agent\n", | ||
1674 | __func__, netxen_nic_driver_name); | ||
1675 | break; | ||
1676 | } | ||
1677 | |||
1678 | start = off0[i] >> 2; | ||
1679 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1680 | for (k = start; k <= end; k++) { | ||
1681 | word[i] |= ((uint64_t) readl( | ||
1682 | (void *)(mem_crb + | ||
1683 | MIU_TEST_AGT_RDDATA(k))) << (32*k)); | ||
1684 | } | ||
1685 | } | ||
1686 | |||
1687 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1688 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1689 | |||
1690 | if (j >= MAX_CTL_CHECK) | ||
1691 | return -1; | ||
1692 | |||
1693 | if (sz[0] == 8) { | ||
1694 | val = word[0]; | ||
1695 | } else { | ||
1696 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
1697 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
1698 | } | ||
1699 | |||
1700 | switch (size) { | ||
1701 | case 1: | ||
1702 | *(uint8_t *)data = val; | ||
1703 | break; | ||
1704 | case 2: | ||
1705 | *(uint16_t *)data = val; | ||
1706 | break; | ||
1707 | case 4: | ||
1708 | *(uint32_t *)data = val; | ||
1709 | break; | ||
1710 | case 8: | ||
1711 | *(uint64_t *)data = val; | ||
1712 | break; | ||
1713 | } | ||
1714 | DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); | ||
1715 | return 0; | ||
1716 | } | ||
1717 | |||
1718 | int | ||
1719 | netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, | ||
1720 | u64 off, void *data, int size) | ||
1721 | { | ||
1722 | int i, j, ret = 0, loop, sz[2], off0; | ||
1723 | uint32_t temp; | ||
1724 | uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
1725 | |||
1726 | /* | ||
1727 | * If not MN, go check for MS or invalid. | ||
1728 | */ | ||
1729 | if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3) | ||
1730 | mem_crb = NETXEN_CRB_QDR_NET; | ||
1731 | else { | ||
1732 | mem_crb = NETXEN_CRB_DDR_NET; | ||
1733 | if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) | ||
1734 | return netxen_nic_pci_mem_write_direct(adapter, | ||
1735 | off, data, size); | ||
1736 | } | ||
1737 | |||
1738 | off8 = off & 0xfffffff8; | ||
1739 | off0 = off & 0x7; | ||
1740 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1741 | sz[1] = size - sz[0]; | ||
1742 | loop = ((off0 + size - 1) >> 3) + 1; | ||
1743 | |||
1744 | if ((size != 8) || (off0 != 0)) { | ||
1745 | for (i = 0; i < loop; i++) { | ||
1746 | if (adapter->pci_mem_read(adapter, off8 + (i << 3), | ||
1747 | &word[i], 8)) | ||
1748 | return -1; | ||
1749 | } | ||
1750 | } | ||
1751 | |||
1752 | switch (size) { | ||
1753 | case 1: | ||
1754 | tmpw = *((uint8_t *)data); | ||
1755 | break; | ||
1756 | case 2: | ||
1757 | tmpw = *((uint16_t *)data); | ||
1758 | break; | ||
1759 | case 4: | ||
1760 | tmpw = *((uint32_t *)data); | ||
1761 | break; | ||
1762 | case 8: | ||
1763 | default: | ||
1764 | tmpw = *((uint64_t *)data); | ||
1765 | break; | ||
1766 | } | ||
1767 | |||
1768 | word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1769 | word[0] |= tmpw << (off0 * 8); | ||
1770 | |||
1771 | if (loop == 2) { | ||
1772 | word[1] &= ~(~0ULL << (sz[1] * 8)); | ||
1773 | word[1] |= tmpw >> (sz[0] * 8); | ||
1774 | } | ||
1775 | |||
1776 | /* | ||
1777 | * don't lock here - write_wx gets the lock if each time | ||
1778 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1779 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1780 | */ | ||
1781 | |||
1782 | for (i = 0; i < loop; i++) { | ||
1783 | temp = off8 + (i << 3); | ||
1784 | adapter->hw_write_wx(adapter, | ||
1785 | mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4); | ||
1786 | temp = 0; | ||
1787 | adapter->hw_write_wx(adapter, | ||
1788 | mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4); | ||
1789 | temp = word[i] & 0xffffffff; | ||
1790 | adapter->hw_write_wx(adapter, | ||
1791 | mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4); | ||
1792 | temp = (word[i] >> 32) & 0xffffffff; | ||
1793 | adapter->hw_write_wx(adapter, | ||
1794 | mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4); | ||
1795 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1796 | adapter->hw_write_wx(adapter, | ||
1797 | mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); | ||
1798 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1799 | adapter->hw_write_wx(adapter, | ||
1800 | mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); | ||
1801 | |||
1802 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1803 | adapter->hw_read_wx(adapter, | ||
1804 | mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); | ||
1805 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1806 | break; | ||
1807 | } | ||
1808 | |||
1809 | if (j >= MAX_CTL_CHECK) { | ||
1810 | printk(KERN_ERR "%s: Fail to write through agent\n", | ||
1811 | netxen_nic_driver_name); | ||
1812 | ret = -1; | ||
1813 | break; | ||
1814 | } | ||
1815 | } | ||
1816 | |||
1817 | /* | ||
1818 | * netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1819 | * write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1820 | */ | ||
1821 | return ret; | ||
1822 | } | ||
1823 | |||
1824 | int | ||
1825 | netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, | ||
1826 | u64 off, void *data, int size) | ||
1827 | { | ||
1828 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | ||
1829 | uint32_t temp; | ||
1830 | uint64_t off8, val, mem_crb, word[2] = {0, 0}; | ||
1831 | |||
1832 | /* | ||
1833 | * If not MN, go check for MS or invalid. | ||
1834 | */ | ||
1835 | |||
1836 | if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3) | ||
1837 | mem_crb = NETXEN_CRB_QDR_NET; | ||
1838 | else { | ||
1839 | mem_crb = NETXEN_CRB_DDR_NET; | ||
1840 | if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) | ||
1841 | return netxen_nic_pci_mem_read_direct(adapter, | ||
1842 | off, data, size); | ||
1843 | } | ||
1844 | |||
1845 | off8 = off & 0xfffffff8; | ||
1846 | off0[0] = off & 0x7; | ||
1847 | off0[1] = 0; | ||
1848 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
1849 | sz[1] = size - sz[0]; | ||
1850 | loop = ((off0[0] + size - 1) >> 3) + 1; | ||
1851 | |||
1852 | /* | ||
1853 | * don't lock here - write_wx gets the lock if each time | ||
1854 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1855 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1856 | */ | ||
1857 | |||
1858 | for (i = 0; i < loop; i++) { | ||
1859 | temp = off8 + (i << 3); | ||
1860 | adapter->hw_write_wx(adapter, | ||
1861 | mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4); | ||
1862 | temp = 0; | ||
1863 | adapter->hw_write_wx(adapter, | ||
1864 | mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4); | ||
1865 | temp = MIU_TA_CTL_ENABLE; | ||
1866 | adapter->hw_write_wx(adapter, | ||
1867 | mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); | ||
1868 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
1869 | adapter->hw_write_wx(adapter, | ||
1870 | mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); | ||
1871 | |||
1872 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1873 | adapter->hw_read_wx(adapter, | ||
1874 | mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); | ||
1875 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1876 | break; | ||
1877 | } | ||
1878 | |||
1879 | if (j >= MAX_CTL_CHECK) { | ||
1880 | printk(KERN_ERR "%s: Fail to read through agent\n", | ||
1881 | netxen_nic_driver_name); | ||
1882 | break; | ||
1883 | } | ||
1884 | |||
1885 | start = off0[i] >> 2; | ||
1886 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1887 | for (k = start; k <= end; k++) { | ||
1888 | adapter->hw_read_wx(adapter, | ||
1889 | mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4); | ||
1890 | word[i] |= ((uint64_t)temp << (32 * k)); | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | /* | ||
1895 | * netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1896 | * write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1897 | */ | ||
1898 | |||
1899 | if (j >= MAX_CTL_CHECK) | ||
1900 | return -1; | ||
1901 | |||
1902 | if (sz[0] == 8) { | ||
1903 | val = word[0]; | ||
1904 | } else { | ||
1905 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
1906 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
1907 | } | ||
1908 | |||
1909 | switch (size) { | ||
1910 | case 1: | ||
1911 | *(uint8_t *)data = val; | ||
1912 | break; | ||
1913 | case 2: | ||
1914 | *(uint16_t *)data = val; | ||
1915 | break; | ||
1916 | case 4: | ||
1917 | *(uint32_t *)data = val; | ||
1918 | break; | ||
1919 | case 8: | ||
1920 | *(uint64_t *)data = val; | ||
1921 | break; | ||
1922 | } | ||
1923 | DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); | ||
1924 | return 0; | ||
1925 | } | ||
1926 | |||
1927 | /* | ||
1928 | * Note : only 32-bit writes! | ||
1929 | */ | ||
1930 | int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, | ||
1931 | u64 off, u32 data) | ||
1932 | { | ||
1933 | adapter->hw_write_wx(adapter, off, &data, 4); | ||
1934 | |||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off) | ||
1939 | { | ||
1940 | u32 temp; | ||
1941 | adapter->hw_read_wx(adapter, off, &temp, 4); | ||
1942 | return temp; | ||
1943 | } | ||
1944 | |||
1945 | void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter, | ||
1946 | u64 off, u32 data) | ||
1947 | { | ||
1948 | adapter->hw_write_wx(adapter, off, &data, 4); | ||
1949 | } | ||
1950 | |||
1951 | u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off) | ||
1952 | { | ||
1953 | u32 temp; | ||
1954 | adapter->hw_read_wx(adapter, off, &temp, 4); | ||
1955 | return temp; | ||
1956 | } | ||
1957 | |||
951 | #if 0 | 1958 | #if 0 |
952 | int | 1959 | int |
953 | netxen_nic_erase_pxe(struct netxen_adapter *adapter) | 1960 | netxen_nic_erase_pxe(struct netxen_adapter *adapter) |
@@ -1003,12 +2010,25 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) | |||
1003 | case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: | 2010 | case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: |
1004 | case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: | 2011 | case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: |
1005 | case NETXEN_BRDTYPE_P2_SB31_10G_CX4: | 2012 | case NETXEN_BRDTYPE_P2_SB31_10G_CX4: |
2013 | case NETXEN_BRDTYPE_P3_HMEZ: | ||
2014 | case NETXEN_BRDTYPE_P3_XG_LOM: | ||
2015 | case NETXEN_BRDTYPE_P3_10G_CX4: | ||
2016 | case NETXEN_BRDTYPE_P3_10G_CX4_LP: | ||
2017 | case NETXEN_BRDTYPE_P3_IMEZ: | ||
2018 | case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: | ||
2019 | case NETXEN_BRDTYPE_P3_10G_XFP: | ||
2020 | case NETXEN_BRDTYPE_P3_10000_BASE_T: | ||
2021 | |||
1006 | adapter->ahw.board_type = NETXEN_NIC_XGBE; | 2022 | adapter->ahw.board_type = NETXEN_NIC_XGBE; |
1007 | break; | 2023 | break; |
1008 | case NETXEN_BRDTYPE_P1_BD: | 2024 | case NETXEN_BRDTYPE_P1_BD: |
1009 | case NETXEN_BRDTYPE_P1_SB: | 2025 | case NETXEN_BRDTYPE_P1_SB: |
1010 | case NETXEN_BRDTYPE_P1_SMAX: | 2026 | case NETXEN_BRDTYPE_P1_SMAX: |
1011 | case NETXEN_BRDTYPE_P1_SOCK: | 2027 | case NETXEN_BRDTYPE_P1_SOCK: |
2028 | case NETXEN_BRDTYPE_P3_REF_QG: | ||
2029 | case NETXEN_BRDTYPE_P3_4_GB: | ||
2030 | case NETXEN_BRDTYPE_P3_4_GB_MM: | ||
2031 | |||
1012 | adapter->ahw.board_type = NETXEN_NIC_GBE; | 2032 | adapter->ahw.board_type = NETXEN_NIC_GBE; |
1013 | break; | 2033 | break; |
1014 | default: | 2034 | default: |
@@ -1042,25 +2062,11 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu) | |||
1042 | return 0; | 2062 | return 0; |
1043 | } | 2063 | } |
1044 | 2064 | ||
1045 | void netxen_nic_init_niu_gb(struct netxen_adapter *adapter) | ||
1046 | { | ||
1047 | netxen_niu_gbe_init_port(adapter, adapter->physical_port); | ||
1048 | } | ||
1049 | |||
1050 | void | 2065 | void |
1051 | netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, | 2066 | netxen_crb_writelit_adapter(struct netxen_adapter *adapter, |
1052 | int data) | 2067 | unsigned long off, int data) |
1053 | { | 2068 | { |
1054 | void __iomem *addr; | 2069 | adapter->hw_write_wx(adapter, off, &data, 4); |
1055 | |||
1056 | if (ADDR_IN_WINDOW1(off)) { | ||
1057 | writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); | ||
1058 | } else { | ||
1059 | netxen_nic_pci_change_crbwindow(adapter, 0); | ||
1060 | addr = pci_base_offset(adapter, off); | ||
1061 | writel(data, addr); | ||
1062 | netxen_nic_pci_change_crbwindow(adapter, 1); | ||
1063 | } | ||
1064 | } | 2070 | } |
1065 | 2071 | ||
1066 | void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) | 2072 | void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) |
@@ -1147,12 +2153,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) | |||
1147 | addr += sizeof(u32); | 2153 | addr += sizeof(u32); |
1148 | } | 2154 | } |
1149 | 2155 | ||
1150 | fw_major = readl(NETXEN_CRB_NORMALIZE(adapter, | 2156 | adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4); |
1151 | NETXEN_FW_VERSION_MAJOR)); | 2157 | adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4); |
1152 | fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter, | 2158 | adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4); |
1153 | NETXEN_FW_VERSION_MINOR)); | 2159 | |
1154 | fw_build = | 2160 | adapter->fw_major = fw_major; |
1155 | readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB)); | ||
1156 | 2161 | ||
1157 | if (adapter->portnum == 0) { | 2162 | if (adapter->portnum == 0) { |
1158 | get_brd_name_by_type(board_info->board_type, brd_name); | 2163 | get_brd_name_by_type(board_info->board_type, brd_name); |
@@ -1163,28 +2168,13 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) | |||
1163 | fw_minor, fw_build); | 2168 | fw_minor, fw_build); |
1164 | } | 2169 | } |
1165 | 2170 | ||
1166 | if (fw_major != _NETXEN_NIC_LINUX_MAJOR) { | 2171 | if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) < |
1167 | adapter->driver_mismatch = 1; | 2172 | NETXEN_VERSION_CODE(3, 4, 216)) { |
1168 | } | ||
1169 | if (fw_minor != _NETXEN_NIC_LINUX_MINOR && | ||
1170 | fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) { | ||
1171 | adapter->driver_mismatch = 1; | 2173 | adapter->driver_mismatch = 1; |
1172 | } | 2174 | printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n", |
1173 | if (adapter->driver_mismatch) { | 2175 | netxen_nic_driver_name, |
1174 | printk(KERN_ERR "%s: driver and firmware version mismatch\n", | 2176 | fw_major, fw_minor, fw_build); |
1175 | adapter->netdev->name); | ||
1176 | return; | 2177 | return; |
1177 | } | 2178 | } |
1178 | |||
1179 | switch (adapter->ahw.board_type) { | ||
1180 | case NETXEN_NIC_GBE: | ||
1181 | dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", | ||
1182 | adapter->netdev->name); | ||
1183 | break; | ||
1184 | case NETXEN_NIC_XGBE: | ||
1185 | dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n", | ||
1186 | adapter->netdev->name); | ||
1187 | break; | ||
1188 | } | ||
1189 | } | 2179 | } |
1190 | 2180 | ||