1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Source file containing the implementation of the Hardware specific
29  * functions
30  */
31 
32 #include <oce_impl.h>
33 #include <oce_stat.h>
34 #include <oce_ioctl.h>
35 
36 static ddi_device_acc_attr_t reg_accattr = {
37 	DDI_DEVICE_ATTR_V1,
38 	DDI_STRUCTURE_LE_ACC,
39 	DDI_STRICTORDER_ACC,
40 	DDI_FLAGERR_ACC
41 };
42 
43 extern int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx,
44     size_t req_size, enum qtype qtype);
45 
46 static int
47 oce_map_regs(struct oce_dev *dev)
48 {
49 	int ret = 0;
50 	off_t bar_size = 0;
51 
52 	ASSERT(NULL != dev);
53 	ASSERT(NULL != dev->dip);
54 
55 	/* get number of supported bars */
56 	ret = ddi_dev_nregs(dev->dip, &dev->num_bars);
57 	if (ret != DDI_SUCCESS) {
58 		oce_log(dev, CE_WARN, MOD_CONFIG,
59 		    "%d: could not retrieve num_bars", MOD_CONFIG);
60 		return (DDI_FAILURE);
61 	}
62 
63 	/* verify each bar and map it accordingly */
64 	/* PCI CFG */
65 	ret = ddi_dev_regsize(dev->dip, OCE_DEV_CFG_BAR, &bar_size);
66 	if (ret != DDI_SUCCESS) {
67 		oce_log(dev, CE_WARN, MOD_CONFIG,
68 		    "Could not get sizeof BAR %d",
69 		    OCE_DEV_CFG_BAR);
70 		return (DDI_FAILURE);
71 	}
72 
73 	ret = ddi_regs_map_setup(dev->dip, OCE_DEV_CFG_BAR, &dev->dev_cfg_addr,
74 	    0, bar_size, &reg_accattr, &dev->dev_cfg_handle);
75 
76 	if (ret != DDI_SUCCESS) {
77 		oce_log(dev, CE_WARN, MOD_CONFIG,
78 		    "Could not map bar %d",
79 		    OCE_DEV_CFG_BAR);
80 		return (DDI_FAILURE);
81 	}
82 
83 	/* CSR */
84 	ret = ddi_dev_regsize(dev->dip, OCE_PCI_CSR_BAR, &bar_size);
85 
86 	if (ret != DDI_SUCCESS) {
87 		oce_log(dev, CE_WARN, MOD_CONFIG,
88 		    "Could not get sizeof BAR %d",
89 		    OCE_PCI_CSR_BAR);
90 		return (DDI_FAILURE);
91 	}
92 
93 	ret = ddi_regs_map_setup(dev->dip, OCE_PCI_CSR_BAR, &dev->csr_addr,
94 	    0, bar_size, &reg_accattr, &dev->csr_handle);
95 	if (ret != DDI_SUCCESS) {
96 		oce_log(dev, CE_WARN, MOD_CONFIG,
97 		    "Could not map bar %d",
98 		    OCE_PCI_CSR_BAR);
99 		ddi_regs_map_free(&dev->dev_cfg_handle);
100 		return (DDI_FAILURE);
101 	}
102 
103 	/* Doorbells */
104 	ret = ddi_dev_regsize(dev->dip, OCE_PCI_DB_BAR, &bar_size);
105 	if (ret != DDI_SUCCESS) {
106 		oce_log(dev, CE_WARN, MOD_CONFIG,
107 		    "%d Could not get sizeof BAR %d",
108 		    ret, OCE_PCI_DB_BAR);
109 		ddi_regs_map_free(&dev->csr_handle);
110 		ddi_regs_map_free(&dev->dev_cfg_handle);
111 		return (DDI_FAILURE);
112 	}
113 
114 	ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr,
115 	    0, 0, &reg_accattr, &dev->db_handle);
116 	if (ret != DDI_SUCCESS) {
117 		oce_log(dev, CE_WARN, MOD_CONFIG,
118 		    "Could not map bar %d", OCE_PCI_DB_BAR);
119 		ddi_regs_map_free(&dev->csr_handle);
120 		ddi_regs_map_free(&dev->dev_cfg_handle);
121 		return (DDI_FAILURE);
122 	}
123 	return (DDI_SUCCESS);
124 }
125 static void
126 oce_unmap_regs(struct oce_dev *dev)
127 {
128 
129 	ASSERT(NULL != dev);
130 	ASSERT(NULL != dev->dip);
131 
132 	ddi_regs_map_free(&dev->db_handle);
133 	ddi_regs_map_free(&dev->csr_handle);
134 	ddi_regs_map_free(&dev->dev_cfg_handle);
135 
136 }
137 
138 
139 
140 
141 
142 /*
143  * function to map the device memory
144  *
145  * dev - handle to device private data structure
146  *
147  */
148 int
149 oce_pci_init(struct oce_dev *dev)
150 {
151 	int ret = 0;
152 
153 	ret = pci_config_setup(dev->dip, &dev->pci_cfg_handle);
154 	if (ret != DDI_SUCCESS) {
155 		return (DDI_FAILURE);
156 	}
157 
158 	ret = oce_map_regs(dev);
159 
160 	if (ret != DDI_SUCCESS) {
161 		pci_config_teardown(&dev->pci_cfg_handle);
162 		return (DDI_FAILURE);
163 	}
164 	dev->fn =  OCE_PCI_FUNC(dev);
165 	if (oce_fm_check_acc_handle(dev, dev->dev_cfg_handle) != DDI_FM_OK) {
166 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
167 	}
168 
169 	if (ret != DDI_FM_OK) {
170 		oce_pci_fini(dev);
171 		return (DDI_FAILURE);
172 	}
173 
174 	return (DDI_SUCCESS);
175 } /* oce_pci_init */
176 
177 /*
178  * function to free device memory mapping mapped using
179  * oce_pci_init
180  *
181  * dev - handle to device private data
182  */
183 void
184 oce_pci_fini(struct oce_dev *dev)
185 {
186 	oce_unmap_regs(dev);
187 	pci_config_teardown(&dev->pci_cfg_handle);
188 } /* oce_pci_fini */
189 
190 
191 /*
192  * function to check if a reset is required
193  *
194  * dev - software handle to the device
195  *
196  */
197 boolean_t
198 oce_is_reset_pci(struct oce_dev *dev)
199 {
200 	mpu_ep_semaphore_t post_status;
201 
202 	ASSERT(dev != NULL);
203 	ASSERT(dev->dip != NULL);
204 
205 	post_status.dw0 = 0;
206 	post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
207 
208 	if (post_status.bits.stage == POST_STAGE_ARMFW_READY) {
209 		return (B_FALSE);
210 	}
211 	return (B_TRUE);
212 } /* oce_is_reset_pci */
213 
214 /*
215  * function to do a soft reset on the device
216  *
217  * dev - software handle to the device
218  *
219  */
220 int
221 oce_pci_soft_reset(struct oce_dev *dev)
222 {
223 	pcicfg_soft_reset_t soft_rst;
224 	/* struct mpu_ep_control ep_control; */
225 	/* struct pcicfg_online1 online1; */
226 	clock_t tmo;
227 	clock_t earlier = ddi_get_lbolt();
228 
229 	ASSERT(dev != NULL);
230 
231 	/* issue soft reset */
232 	soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET);
233 	soft_rst.bits.soft_reset = 0x01;
234 	OCE_CFG_WRITE32(dev, PCICFG_SOFT_RESET, soft_rst.dw0);
235 
236 	/* wait till soft reset bit deasserts */
237 	tmo = drv_usectohz(60000000); /* 1.0min */
238 	do {
239 		if ((ddi_get_lbolt() - earlier) > tmo) {
240 			tmo = 0;
241 			break;
242 		}
243 
244 		soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET);
245 		if (soft_rst.bits.soft_reset)
246 			drv_usecwait(100);
247 	} while (soft_rst.bits.soft_reset);
248 
249 	if (soft_rst.bits.soft_reset) {
250 		oce_log(dev, CE_WARN, MOD_CONFIG,
251 		    "0x%x soft_reset"
252 		    "bit asserted[1]. Reset failed",
253 		    soft_rst.dw0);
254 		return (DDI_FAILURE);
255 	}
256 
257 	return (oce_POST(dev));
258 } /* oce_pci_soft_reset */
259 /*
260  * function to trigger a POST on the device
261  *
262  * dev - software handle to the device
263  *
264  */
265 int
266 oce_POST(struct oce_dev *dev)
267 {
268 	mpu_ep_semaphore_t post_status;
269 	clock_t tmo;
270 	clock_t earlier = ddi_get_lbolt();
271 
272 	/* read semaphore CSR */
273 	post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
274 	if (oce_fm_check_acc_handle(dev, dev->csr_handle) != DDI_FM_OK) {
275 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
276 		return (DDI_FAILURE);
277 	}
278 	/* if host is ready then wait for fw ready else send POST */
279 	if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
280 		post_status.bits.stage = POST_STAGE_CHIP_RESET;
281 		OCE_CSR_WRITE32(dev, MPU_EP_SEMAPHORE, post_status.dw0);
282 		if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
283 		    DDI_FM_OK) {
284 			ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
285 			return (DDI_FAILURE);
286 		}
287 	}
288 
289 	/* wait for FW ready */
290 	tmo = drv_usectohz(60000000); /* 1.0min */
291 	for (;;) {
292 		if ((ddi_get_lbolt() - earlier) > tmo) {
293 			tmo = 0;
294 			break;
295 		}
296 
297 		post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
298 		if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
299 		    DDI_FM_OK) {
300 			ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
301 			return (DDI_FAILURE);
302 		}
303 		if (post_status.bits.error) {
304 			oce_log(dev, CE_WARN, MOD_CONFIG,
305 			    "0x%x POST ERROR!!", post_status.dw0);
306 			return (DDI_FAILURE);
307 		}
308 		if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
309 			return (DDI_SUCCESS);
310 
311 		drv_usecwait(100);
312 	}
313 	return (DDI_FAILURE);
314 } /* oce_POST */
315 /*
316  * function to modify register access attributes corresponding to the
317  * FM capabilities configured by the user
318  *
319  * fm_caps - fm capability configured by the user and accepted by the driver
320  */
321 void
322 oce_set_reg_fma_flags(int fm_caps)
323 {
324 	if (fm_caps == DDI_FM_NOT_CAPABLE) {
325 		return;
326 	}
327 	if (DDI_FM_ACC_ERR_CAP(fm_caps)) {
328 		reg_accattr.devacc_attr_access = DDI_FLAGERR_ACC;
329 	} else {
330 		reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC;
331 	}
332 } /* oce_set_fma_flags */
333 
334 
335 int
336 oce_create_nw_interface(struct oce_dev *dev)
337 {
338 	int ret;
339 	uint32_t capab_flags = OCE_CAPAB_FLAGS;
340 	uint32_t capab_en_flags = OCE_CAPAB_ENABLE;
341 
342 	if (dev->rss_enable) {
343 		capab_flags |= MBX_RX_IFACE_FLAGS_RSS;
344 		capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS;
345 	}
346 
347 	/* create an interface for the device with out mac */
348 	ret = oce_if_create(dev, capab_flags, capab_en_flags,
349 	    0, &dev->mac_addr[0], (uint32_t *)&dev->if_id);
350 	if (ret != 0) {
351 		oce_log(dev, CE_WARN, MOD_CONFIG,
352 		    "Interface creation failed: 0x%x", ret);
353 		return (ret);
354 	}
355 	atomic_inc_32(&dev->nifs);
356 
357 	dev->if_cap_flags = capab_en_flags;
358 
359 	/* Enable VLAN Promisc on HW */
360 	ret = oce_config_vlan(dev, (uint8_t)dev->if_id, NULL, 0,
361 	    B_TRUE, B_TRUE);
362 	if (ret != 0) {
363 		oce_log(dev, CE_WARN, MOD_CONFIG,
364 		    "Config vlan failed: %d", ret);
365 		oce_delete_nw_interface(dev);
366 		return (ret);
367 
368 	}
369 
370 	/* set default flow control */
371 	ret = oce_set_flow_control(dev, dev->flow_control);
372 	if (ret != 0) {
373 		oce_log(dev, CE_NOTE, MOD_CONFIG,
374 		    "Set flow control failed: %d", ret);
375 	}
376 	ret = oce_set_promiscuous(dev, dev->promisc);
377 
378 	if (ret != 0) {
379 		oce_log(dev, CE_NOTE, MOD_CONFIG,
380 		    "Set Promisc failed: %d", ret);
381 	}
382 
383 	return (0);
384 }
385 
386 void
387 oce_delete_nw_interface(struct oce_dev *dev) {
388 
389 	/* currently only single interface is implmeneted */
390 	if (dev->nifs > 0) {
391 		(void) oce_if_del(dev, dev->if_id);
392 		atomic_dec_32(&dev->nifs);
393 	}
394 }
395 
396 static void
397 oce_create_itbl(struct oce_dev *dev, char *itbl)
398 {
399 	int i;
400 	struct oce_rq **rss_queuep = &dev->rq[1];
401 	int nrss  = dev->nrqs - 1;
402 	/* fill the indirection table rq 0 is default queue */
403 	for (i = 0; i < OCE_ITBL_SIZE; i++) {
404 		itbl[i] = rss_queuep[i % nrss]->rss_cpuid;
405 	}
406 }
407 
408 int
409 oce_setup_adapter(struct oce_dev *dev)
410 {
411 	int ret;
412 	char itbl[OCE_ITBL_SIZE];
413 	char hkey[OCE_HKEY_SIZE];
414 
415 	/* disable the interrupts here and enable in start */
416 	oce_chip_di(dev);
417 
418 	ret = oce_create_nw_interface(dev);
419 	if (ret != DDI_SUCCESS) {
420 		return (DDI_FAILURE);
421 	}
422 	ret = oce_create_queues(dev);
423 	if (ret != DDI_SUCCESS) {
424 		oce_delete_nw_interface(dev);
425 		return (DDI_FAILURE);
426 	}
427 	if (dev->rss_enable) {
428 		(void) oce_create_itbl(dev, itbl);
429 		(void) oce_gen_hkey(hkey, OCE_HKEY_SIZE);
430 		ret = oce_config_rss(dev, dev->if_id, hkey, itbl, OCE_ITBL_SIZE,
431 		    OCE_DEFAULT_RSS_TYPE, B_TRUE);
432 		if (ret != DDI_SUCCESS) {
433 			oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
434 			    "Failed to Configure RSS");
435 			oce_delete_queues(dev);
436 			oce_delete_nw_interface(dev);
437 			return (ret);
438 		}
439 	}
440 	ret = oce_setup_handlers(dev);
441 	if (ret != DDI_SUCCESS) {
442 		oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
443 		    "Failed to Setup handlers");
444 		oce_delete_queues(dev);
445 		oce_delete_nw_interface(dev);
446 		return (ret);
447 	}
448 	return (DDI_SUCCESS);
449 }
450 
451 void
452 oce_unsetup_adapter(struct oce_dev *dev)
453 {
454 	oce_remove_handler(dev);
455 	if (dev->rss_enable) {
456 		char itbl[OCE_ITBL_SIZE] = {0};
457 		char hkey[OCE_HKEY_SIZE] = {0};
458 		int ret = 0;
459 
460 		ret = oce_config_rss(dev, dev->if_id, hkey, itbl, OCE_ITBL_SIZE,
461 		    RSS_ENABLE_NONE, B_TRUE);
462 
463 		if (ret != DDI_SUCCESS) {
464 			oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
465 			    "Failed to Disable RSS");
466 		}
467 	}
468 	oce_delete_queues(dev);
469 	oce_delete_nw_interface(dev);
470 }
471 
472 int
473 oce_hw_init(struct oce_dev *dev)
474 {
475 	int  ret;
476 	struct mac_address_format mac_addr;
477 
478 	ret = oce_POST(dev);
479 	if (ret != DDI_SUCCESS) {
480 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
481 		    "!!!HW POST1 FAILED");
482 		/* ADD FM FAULT */
483 		return (DDI_FAILURE);
484 	}
485 	/* create bootstrap mailbox */
486 	dev->bmbx = oce_alloc_dma_buffer(dev,
487 	    sizeof (struct oce_bmbx), NULL, DDI_DMA_CONSISTENT);
488 	if (dev->bmbx == NULL) {
489 		oce_log(dev, CE_WARN, MOD_CONFIG,
490 		    "Failed to allocate bmbx: size = %u",
491 		    (uint32_t)sizeof (struct oce_bmbx));
492 		return (DDI_FAILURE);
493 	}
494 
495 	ret = oce_reset_fun(dev);
496 	if (ret != 0) {
497 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
498 		    "!!!FUNCTION RESET FAILED");
499 		goto init_fail;
500 	}
501 
502 	/* reset the Endianess of BMBX */
503 	ret = oce_mbox_init(dev);
504 	if (ret != 0) {
505 		oce_log(dev, CE_WARN, MOD_CONFIG,
506 		    "Mailbox initialization2 Failed with %d", ret);
507 		goto init_fail;
508 	}
509 
510 	/* read the firmware version */
511 	ret = oce_get_fw_version(dev);
512 	if (ret != 0) {
513 		oce_log(dev, CE_WARN, MOD_CONFIG,
514 		    "Firmaware version read failed with %d", ret);
515 		goto init_fail;
516 	}
517 
518 	/* read the fw config */
519 	ret = oce_get_fw_config(dev);
520 	if (ret != 0) {
521 		oce_log(dev, CE_WARN, MOD_CONFIG,
522 		    "Firmware configuration read failed with %d", ret);
523 		goto init_fail;
524 	}
525 
526 	/* read the Factory MAC address */
527 	ret = oce_read_mac_addr(dev, 0, 1,
528 	    MAC_ADDRESS_TYPE_NETWORK, &mac_addr);
529 	if (ret != 0) {
530 		oce_log(dev, CE_WARN, MOD_CONFIG,
531 		    "MAC address read failed with %d", ret);
532 		goto init_fail;
533 	}
534 	bcopy(&mac_addr.mac_addr[0], &dev->mac_addr[0], ETHERADDRL);
535 	return (DDI_SUCCESS);
536 init_fail:
537 	oce_hw_fini(dev);
538 	return (DDI_FAILURE);
539 }
540 void
541 oce_hw_fini(struct oce_dev *dev)
542 {
543 	if (dev->bmbx != NULL) {
544 		oce_free_dma_buffer(dev, dev->bmbx);
545 		dev->bmbx = NULL;
546 	}
547 }
548