]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Kieran Mansley <kmansley@solarflare.com> |
2 | Subject: enable access to Falcon's external SRAM | |
3 | References: bnc#489105 | |
4 | ||
5 | Include ability to reference external SRAM on Solarflare Falcon NICs to | |
6 | allow event queues to be accessed by virtualised guests. | |
7 | ||
8 | Acked-by: bphilips@novell.com | |
9 | ||
10 | --- sle11-2009-04-09.orig/drivers/net/sfc/falcon.c 2009-03-30 15:58:20.000000000 +0200 | |
11 | +++ sle11-2009-04-09/drivers/net/sfc/falcon.c 2009-03-30 15:58:59.000000000 +0200 | |
12 | @@ -36,12 +36,18 @@ | |
13 | ||
14 | /** | |
15 | * struct falcon_nic_data - Falcon NIC state | |
16 | + * @sram_cfg: SRAM configuration value | |
17 | + * @tx_dc_base: Base address in SRAM of TX queue descriptor caches | |
18 | + * @rx_dc_base: Base address in SRAM of RX queue descriptor caches | |
19 | * @next_buffer_table: First available buffer table id | |
20 | * @resources: Resource information for driverlink client | |
21 | * @pci_dev2: The secondary PCI device if present | |
22 | * @i2c_data: Operations and state for I2C bit-bashing algorithm | |
23 | */ | |
24 | struct falcon_nic_data { | |
25 | + int sram_cfg; | |
26 | + unsigned tx_dc_base; | |
27 | + unsigned rx_dc_base; | |
28 | #ifndef CONFIG_SFC_DRIVERLINK | |
29 | unsigned next_buffer_table; | |
30 | #else | |
31 | @@ -69,11 +75,11 @@ static int disable_dma_stats; | |
32 | */ | |
33 | #define TX_DC_ENTRIES 16 | |
34 | #define TX_DC_ENTRIES_ORDER 0 | |
35 | -#define TX_DC_BASE 0x130000 | |
36 | +#define TX_DC_INTERNAL_BASE 0x130000 | |
37 | ||
38 | #define RX_DC_ENTRIES 64 | |
39 | #define RX_DC_ENTRIES_ORDER 2 | |
40 | -#define RX_DC_BASE 0x100000 | |
41 | +#define RX_DC_INTERNAL_BASE 0x100000 | |
42 | ||
43 | /* RX FIFO XOFF watermark | |
44 | * | |
45 | @@ -454,9 +460,17 @@ void falcon_push_buffers(struct efx_tx_q | |
46 | int falcon_probe_tx(struct efx_tx_queue *tx_queue) | |
47 | { | |
48 | struct efx_nic *efx = tx_queue->efx; | |
49 | - return falcon_alloc_special_buffer(efx, &tx_queue->txd, | |
50 | - FALCON_TXD_RING_SIZE * | |
51 | - sizeof(efx_qword_t)); | |
52 | + int rc = falcon_alloc_special_buffer(efx, &tx_queue->txd, | |
53 | + FALCON_TXD_RING_SIZE * | |
54 | + sizeof(efx_qword_t)); | |
55 | +#ifdef CONFIG_SFC_DRIVERLINK | |
56 | + if (rc == 0) { | |
57 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
58 | + nic_data->resources.txq_min = max(nic_data->resources.txq_min, | |
59 | + (unsigned)tx_queue->queue + 1); | |
60 | + } | |
61 | +#endif | |
62 | + return rc; | |
63 | } | |
64 | ||
65 | int falcon_init_tx(struct efx_tx_queue *tx_queue) | |
66 | @@ -643,9 +657,17 @@ void falcon_notify_rx_desc(struct efx_rx | |
67 | int falcon_probe_rx(struct efx_rx_queue *rx_queue) | |
68 | { | |
69 | struct efx_nic *efx = rx_queue->efx; | |
70 | - return falcon_alloc_special_buffer(efx, &rx_queue->rxd, | |
71 | - FALCON_RXD_RING_SIZE * | |
72 | - sizeof(efx_qword_t)); | |
73 | + int rc = falcon_alloc_special_buffer(efx, &rx_queue->rxd, | |
74 | + FALCON_RXD_RING_SIZE * | |
75 | + sizeof(efx_qword_t)); | |
76 | +#ifdef CONFIG_SFC_DRIVERLINK | |
77 | + if (rc == 0) { | |
78 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
79 | + nic_data->resources.rxq_min = max(nic_data->resources.rxq_min, | |
80 | + (unsigned)rx_queue->queue + 1); | |
81 | + } | |
82 | +#endif | |
83 | + return rc; | |
84 | } | |
85 | ||
86 | int falcon_init_rx(struct efx_rx_queue *rx_queue) | |
87 | @@ -1276,9 +1298,18 @@ int falcon_probe_eventq(struct efx_chann | |
88 | { | |
89 | struct efx_nic *efx = channel->efx; | |
90 | unsigned int evq_size; | |
91 | + int rc; | |
92 | ||
93 | evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t); | |
94 | - return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size); | |
95 | + rc = falcon_alloc_special_buffer(efx, &channel->eventq, evq_size); | |
96 | +#ifdef CONFIG_SFC_DRIVERLINK | |
97 | + if (rc == 0) { | |
98 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
99 | + nic_data->resources.evq_int_min = max(nic_data->resources.evq_int_min, | |
100 | + (unsigned)channel->evqnum + 1); | |
101 | + } | |
102 | +#endif | |
103 | + return rc; | |
104 | } | |
105 | ||
106 | int falcon_init_eventq(struct efx_channel *channel) | |
107 | @@ -2285,19 +2316,22 @@ fail5: | |
108 | */ | |
109 | static int falcon_reset_sram(struct efx_nic *efx) | |
110 | { | |
111 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
112 | efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker; | |
113 | - int count; | |
114 | + int count, onchip, sram_cfg_val; | |
115 | ||
116 | /* Set the SRAM wake/sleep GPIO appropriately. */ | |
117 | + onchip = (nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY); | |
118 | falcon_read(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); | |
119 | EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OEN, 1); | |
120 | - EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, 1); | |
121 | + EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, onchip); | |
122 | falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); | |
123 | ||
124 | /* Initiate SRAM reset */ | |
125 | + sram_cfg_val = onchip ? 0 : nic_data->sram_cfg; | |
126 | EFX_POPULATE_OWORD_2(srm_cfg_reg_ker, | |
127 | SRAM_OOB_BT_INIT_EN, 1, | |
128 | - SRM_NUM_BANKS_AND_BANK_SIZE, 0); | |
129 | + SRM_NUM_BANKS_AND_BANK_SIZE, sram_cfg_val); | |
130 | falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER); | |
131 | ||
132 | /* Wait for SRAM reset to complete */ | |
133 | @@ -2324,12 +2358,14 @@ static int falcon_reset_sram(struct efx_ | |
134 | /* Extract non-volatile configuration */ | |
135 | static int falcon_probe_nvconfig(struct efx_nic *efx) | |
136 | { | |
137 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
138 | struct falcon_nvconfig *nvconfig; | |
139 | efx_oword_t nic_stat; | |
140 | int device_id; | |
141 | unsigned addr_len; | |
142 | size_t offset, len; | |
143 | int magic_num, struct_ver, board_rev; | |
144 | + bool onchip_sram; | |
145 | int rc; | |
146 | ||
147 | /* Find the boot device. */ | |
148 | @@ -2370,18 +2406,41 @@ static int falcon_probe_nvconfig(struct | |
149 | efx->phy_type = PHY_TYPE_NONE; | |
150 | efx->mii.phy_id = PHY_ADDR_INVALID; | |
151 | board_rev = 0; | |
152 | + onchip_sram = true; | |
153 | } else { | |
154 | struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2; | |
155 | ||
156 | efx->phy_type = v2->port0_phy_type; | |
157 | efx->mii.phy_id = v2->port0_phy_addr; | |
158 | board_rev = le16_to_cpu(v2->board_revision); | |
159 | +#ifdef CONFIG_SFC_DRIVERLINK | |
160 | + onchip_sram = EFX_OWORD_FIELD(nvconfig->nic_stat_reg, | |
161 | + ONCHIP_SRAM); | |
162 | +#else | |
163 | + /* We have no use for external SRAM */ | |
164 | + onchip_sram = true; | |
165 | +#endif | |
166 | } | |
167 | ||
168 | EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); | |
169 | ||
170 | efx_set_board_info(efx, board_rev); | |
171 | ||
172 | + /* Read the SRAM configuration. The register is initialised | |
173 | + * automatically but might may been reset since boot. | |
174 | + */ | |
175 | + if (onchip_sram) { | |
176 | + nic_data->sram_cfg = SRM_NB_BSZ_ONCHIP_ONLY; | |
177 | + } else { | |
178 | + nic_data->sram_cfg = | |
179 | + EFX_OWORD_FIELD(nvconfig->srm_cfg_reg, | |
180 | + SRM_NUM_BANKS_AND_BANK_SIZE); | |
181 | + WARN_ON(nic_data->sram_cfg == SRM_NB_BSZ_RESERVED); | |
182 | + /* Replace invalid setting with the smallest defaults */ | |
183 | + if (nic_data->sram_cfg == SRM_NB_BSZ_DEFAULT) | |
184 | + nic_data->sram_cfg = SRM_NB_BSZ_1BANKS_2M; | |
185 | + } | |
186 | + | |
187 | out: | |
188 | kfree(nvconfig); | |
189 | return rc; | |
190 | @@ -2392,9 +2451,9 @@ static int falcon_probe_nvconfig(struct | |
191 | * should live. */ | |
192 | static int falcon_dimension_resources(struct efx_nic *efx) | |
193 | { | |
194 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
195 | #ifdef CONFIG_SFC_DRIVERLINK | |
196 | unsigned internal_dcs_entries; | |
197 | - struct falcon_nic_data *nic_data = efx->nic_data; | |
198 | struct efx_dl_falcon_resources *res = &nic_data->resources; | |
199 | ||
200 | /* Fill out the driverlink resource list */ | |
201 | @@ -2427,16 +2486,64 @@ static int falcon_dimension_resources(st | |
202 | break; | |
203 | } | |
204 | ||
205 | - /* Internal SRAM only for now */ | |
206 | - res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES; | |
207 | - res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES; | |
208 | - res->buffer_table_lim = 8192; | |
209 | + if (nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY) { | |
210 | + res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES; | |
211 | + res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES; | |
212 | + res->buffer_table_lim = 8192; | |
213 | + nic_data->tx_dc_base = TX_DC_INTERNAL_BASE; | |
214 | + nic_data->rx_dc_base = RX_DC_INTERNAL_BASE; | |
215 | + } else { | |
216 | + unsigned sram_bytes, vnic_bytes, max_vnics, n_vnics, dcs; | |
217 | + | |
218 | + /* Determine how much SRAM we have to play with. We have | |
219 | + * to fit buffer table and descriptor caches in. | |
220 | + */ | |
221 | + switch (nic_data->sram_cfg) { | |
222 | + case SRM_NB_BSZ_1BANKS_2M: | |
223 | + default: | |
224 | + sram_bytes = 2 * 1024 * 1024; | |
225 | + break; | |
226 | + case SRM_NB_BSZ_1BANKS_4M: | |
227 | + case SRM_NB_BSZ_2BANKS_4M: | |
228 | + sram_bytes = 4 * 1024 * 1024; | |
229 | + break; | |
230 | + case SRM_NB_BSZ_1BANKS_8M: | |
231 | + case SRM_NB_BSZ_2BANKS_8M: | |
232 | + sram_bytes = 8 * 1024 * 1024; | |
233 | + break; | |
234 | + case SRM_NB_BSZ_2BANKS_16M: | |
235 | + sram_bytes = 16 * 1024 * 1024; | |
236 | + break; | |
237 | + } | |
238 | + /* For each VNIC allow at least 512 buffer table entries | |
239 | + * and descriptor cache for an rxq and txq. Buffer table | |
240 | + * space for evqs and dmaqs is relatively trivial, so not | |
241 | + * considered in this calculation. | |
242 | + */ | |
243 | + vnic_bytes = 512 * 8 + RX_DC_ENTRIES * 8 + TX_DC_ENTRIES * 8; | |
244 | + max_vnics = sram_bytes / vnic_bytes; | |
245 | + for (n_vnics = 1; n_vnics < res->evq_timer_min + max_vnics;) | |
246 | + n_vnics *= 2; | |
247 | + res->rxq_lim = n_vnics; | |
248 | + res->txq_lim = n_vnics; | |
249 | + | |
250 | + dcs = n_vnics * TX_DC_ENTRIES * 8; | |
251 | + nic_data->tx_dc_base = sram_bytes - dcs; | |
252 | + dcs = n_vnics * RX_DC_ENTRIES * 8; | |
253 | + nic_data->rx_dc_base = nic_data->tx_dc_base - dcs; | |
254 | + res->buffer_table_lim = nic_data->rx_dc_base / 8; | |
255 | + } | |
256 | ||
257 | if (FALCON_IS_DUAL_FUNC(efx)) | |
258 | res->flags |= EFX_DL_FALCON_DUAL_FUNC; | |
259 | ||
260 | if (EFX_INT_MODE_USE_MSI(efx)) | |
261 | res->flags |= EFX_DL_FALCON_USE_MSI; | |
262 | +#else | |
263 | + /* We ignore external SRAM */ | |
264 | + EFX_BUG_ON_PARANOID(nic_data->sram_cfg != SRM_NB_BSZ_ONCHIP_ONLY); | |
265 | + nic_data->tx_dc_base = TX_DC_INTERNAL_BASE; | |
266 | + nic_data->rx_dc_base = RX_DC_INTERNAL_BASE; | |
267 | #endif | |
268 | ||
269 | return 0; | |
270 | @@ -2586,6 +2693,7 @@ int falcon_probe_nic(struct efx_nic *efx | |
271 | */ | |
272 | int falcon_init_nic(struct efx_nic *efx) | |
273 | { | |
274 | + struct falcon_nic_data *nic_data = efx->nic_data; | |
275 | efx_oword_t temp; | |
276 | unsigned thresh; | |
277 | int rc; | |
278 | @@ -2599,9 +2707,10 @@ int falcon_init_nic(struct efx_nic *efx) | |
279 | ADR_REGION3, (3 << 16)); | |
280 | falcon_write(efx, &temp, ADR_REGION_REG_KER); | |
281 | ||
282 | - /* Use on-chip SRAM */ | |
283 | + /* Use on-chip SRAM if wanted. */ | |
284 | falcon_read(efx, &temp, NIC_STAT_REG); | |
285 | - EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); | |
286 | + EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, | |
287 | + nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY); | |
288 | falcon_write(efx, &temp, NIC_STAT_REG); | |
289 | ||
290 | /* Set buffer table mode */ | |
291 | @@ -2613,9 +2722,9 @@ int falcon_init_nic(struct efx_nic *efx) | |
292 | return rc; | |
293 | ||
294 | /* Set positions of descriptor caches in SRAM. */ | |
295 | - EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, TX_DC_BASE / 8); | |
296 | + EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, nic_data->tx_dc_base / 8); | |
297 | falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER); | |
298 | - EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, RX_DC_BASE / 8); | |
299 | + EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, nic_data->rx_dc_base / 8); | |
300 | falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER); | |
301 | ||
302 | /* Set TX descriptor cache size. */ |