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