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
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, ®_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
110
111 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr,
112 0, 0, ®_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
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
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
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
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
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
255 oce_is_reset_pci(struct oce_dev *dev)
256 {
257 mpu_ep_semaphore_t post_status;
258
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
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 }
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
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
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
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
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
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
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
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
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 }
|
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 (c) 2009-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28
29 /*
30 * Source file containing the implementation of the Hardware specific
31 * functions
32 */
33
34 #include <oce_impl.h>
35 #include <oce_stat.h>
36 #include <oce_ioctl.h>
37
38 static ddi_device_acc_attr_t reg_accattr = {
39 DDI_DEVICE_ATTR_V1,
40 DDI_STRUCTURE_LE_ACC,
41 DDI_STRICTORDER_ACC,
42 DDI_FLAGERR_ACC
43 };
44
45 extern int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx,
46 size_t req_size, enum qtype qtype, uint32_t mode);
47
48 static int
49 oce_map_regs(struct oce_dev *dev)
50 {
51 int ret = 0;
52 off_t bar_size = 0;
53
54 ASSERT(NULL != dev);
55 ASSERT(NULL != dev->dip);
56
57 /* get number of supported bars */
58 ret = ddi_dev_nregs(dev->dip, &dev->num_bars);
59 if (ret != DDI_SUCCESS) {
60 oce_log(dev, CE_WARN, MOD_CONFIG,
61 "Could not retrieve num_bars, ret =0x%x", ret);
62 return (DDI_FAILURE);
63 }
64
65 if (LANCER_CHIP(dev)) {
66 /* Doorbells */
67 ret = ddi_dev_regsize(dev->dip, OCE_PCI_LANCER_DB_BAR,
68 &bar_size);
69 if (ret != DDI_SUCCESS) {
70 oce_log(dev, CE_WARN, MOD_CONFIG,
71 "%d Could not get sizeof BAR %d",
72 ret, OCE_PCI_LANCER_DB_BAR);
73 return (DDI_FAILURE);
74 }
75
76 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_LANCER_DB_BAR,
77 &dev->db_addr, 0, 0, ®_accattr, &dev->db_handle);
78 if (ret != DDI_SUCCESS) {
79 oce_log(dev, CE_WARN, MOD_CONFIG,
80 "Could not map bar %d", OCE_PCI_LANCER_DB_BAR);
81 return (DDI_FAILURE);
82 }
83 return (DDI_SUCCESS);
84 }
85
86 /* verify each bar and map it accordingly */
87 /* PCI CFG */
88 ret = ddi_dev_regsize(dev->dip, OCE_DEV_CFG_BAR, &bar_size);
89 if (ret != DDI_SUCCESS) {
90 oce_log(dev, CE_WARN, MOD_CONFIG,
91 "Could not get sizeof BAR %d",
92 OCE_DEV_CFG_BAR);
93 return (DDI_FAILURE);
94 }
95
96 ret = ddi_regs_map_setup(dev->dip, OCE_DEV_CFG_BAR, &dev->dev_cfg_addr,
97 0, bar_size, ®_accattr, &dev->dev_cfg_handle);
98
99 if (ret != DDI_SUCCESS) {
100 oce_log(dev, CE_WARN, MOD_CONFIG,
101 "Could not map bar %d",
102 OCE_DEV_CFG_BAR);
103 return (DDI_FAILURE);
104 }
105
136
137 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr,
138 0, 0, ®_accattr, &dev->db_handle);
139 if (ret != DDI_SUCCESS) {
140 oce_log(dev, CE_WARN, MOD_CONFIG,
141 "Could not map bar %d", OCE_PCI_DB_BAR);
142 ddi_regs_map_free(&dev->csr_handle);
143 ddi_regs_map_free(&dev->dev_cfg_handle);
144 return (DDI_FAILURE);
145 }
146 return (DDI_SUCCESS);
147 }
148 static void
149 oce_unmap_regs(struct oce_dev *dev)
150 {
151
152 ASSERT(NULL != dev);
153 ASSERT(NULL != dev->dip);
154
155 ddi_regs_map_free(&dev->db_handle);
156 if (!LANCER_CHIP(dev)) {
157 ddi_regs_map_free(&dev->csr_handle);
158 ddi_regs_map_free(&dev->dev_cfg_handle);
159 }
160
161 }
162
163
164 static void
165 oce_check_slot(struct oce_dev *dev)
166 {
167 uint32_t curr = 0;
168 uint32_t max = 0;
169 uint32_t width = 0;
170 uint32_t max_width = 0;
171 uint32_t speed = 0;
172 uint32_t max_speed = 0;
173
174 curr = OCE_CFG_READ32(dev, PCICFG_PCIE_LINK_STATUS_OFFSET);
175
176 width = (curr >> PCIE_LINK_STATUS_NEG_WIDTH_SHIFT) &
177 PCIE_LINK_STATUS_NEG_WIDTH_MASK;
178 speed = (curr >> PCIE_LINK_STATUS_SPEED_SHIFT) &
179 PCIE_LINK_STATUS_SPEED_MASK;
180
181 oce_log(dev, CE_NOTE, MOD_CONFIG, "Reg value %x"
182 " width %d speed %d\n", curr, width, speed);
183 max = OCE_CFG_READ32(dev, PCICFG_PCIE_LINK_CAP_OFFSET);
184
185 max_width = (max >> PCIE_LINK_CAP_MAX_WIDTH_SHIFT) &
186 PCIE_LINK_CAP_MAX_WIDTH_MASK;
187 max_speed = (max >> PCIE_LINK_CAP_MAX_SPEED_SHIFT) &
188 PCIE_LINK_CAP_MAX_SPEED_MASK;
189 oce_log(dev, CE_NOTE, MOD_CONFIG, "Reg value %x"
190 " max_width %d max_speed %d\n",
191 max, max_width, max_speed);
192
193 if (width < max_width || speed < max_speed) {
194 oce_log(dev, CE_NOTE, MOD_CONFIG,
195 "Found CNA device in a Gen%s x%d PCIe Slot."
196 "It is recommended to be in a Gen2 x%d slot"
197 "for best performance\n",
198 speed < max_speed ? "1" : "2",
199 width, max_width);
200 }
201 }
202
203
204 /*
205 * function to map the device memory
206 *
207 * dev - handle to device private data structure
208 *
209 */
210 int
211 oce_pci_init(struct oce_dev *dev)
212 {
213 int ret = 0;
214
215 ret = oce_map_regs(dev);
216
217 if (ret != DDI_SUCCESS) {
218 return (DDI_FAILURE);
219 }
220
221 if (!LANCER_CHIP(dev)) {
222 dev->fn = OCE_PCI_FUNC(dev);
223 if (oce_fm_check_acc_handle(dev, dev->dev_cfg_handle) !=
224 DDI_FM_OK) {
225 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
226 }
227 }
228
229 if (ret != DDI_FM_OK) {
230 oce_pci_fini(dev);
231 return (DDI_FAILURE);
232 }
233
234 if (!LANCER_CHIP(dev))
235 oce_check_slot(dev);
236
237 return (DDI_SUCCESS);
238 } /* oce_pci_init */
239
240 /*
241 * function to free device memory mapping mapped using
242 * oce_pci_init
243 *
244 * dev - handle to device private data
245 */
246 void
247 oce_pci_fini(struct oce_dev *dev)
248 {
249 oce_unmap_regs(dev);
250 } /* oce_pci_fini */
251
252
253 int
254 oce_identify_hw(struct oce_dev *dev)
255 {
256 int ret = DDI_SUCCESS;
257 uint32_t if_type = 0, sli_intf = 0;
258
259 dev->vendor_id = pci_config_get16(dev->pci_cfg_handle,
260 PCI_CONF_VENID);
261 dev->device_id = pci_config_get16(dev->pci_cfg_handle,
262 PCI_CONF_DEVID);
263 dev->subsys_id = pci_config_get16(dev->pci_cfg_handle,
264 PCI_CONF_SUBSYSID);
265 dev->subvendor_id = pci_config_get16(dev->pci_cfg_handle,
266 PCI_CONF_SUBVENID);
267
268 switch (dev->device_id) {
269
270 case DEVID_TIGERSHARK:
271 dev->chip_rev = OC_CNA_GEN2;
272 /* BE2 hardware properly supports single tx ring */
273 dev->tx_rings = 1;
274 break;
275 case DEVID_TOMCAT:
276 dev->chip_rev = OC_CNA_GEN3;
277 break;
278 case DEVID_LANCER:
279 sli_intf = pci_config_get32(dev->pci_cfg_handle,
280 SLI_INTF_REG_OFFSET);
281
282 if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
283 SLI_INTF_IF_TYPE_SHIFT;
284
285 if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
286 if_type != 0x02) {
287 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
288 "SLI I/F not Valid or different interface type\n");
289 ret = DDI_FAILURE;
290 break;
291 }
292 dev->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
293 SLI_INTF_FAMILY_SHIFT);
294
295 dev->chip_rev = 0;
296 break;
297
298 default:
299 dev->chip_rev = 0;
300 ret = DDI_FAILURE;
301 break;
302 }
303 return (ret);
304 }
305
306
307 /*
308 * function to check if a reset is required
309 *
310 * dev - software handle to the device
311 *
312 */
313 boolean_t
314 oce_is_reset_pci(struct oce_dev *dev)
315 {
316 mpu_ep_semaphore_t post_status;
317
355 if ((ddi_get_lbolt() - earlier) > tmo) {
356 tmo = 0;
357 break;
358 }
359
360 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET);
361 if (soft_rst.bits.soft_reset)
362 drv_usecwait(100);
363 } while (soft_rst.bits.soft_reset);
364
365 if (soft_rst.bits.soft_reset) {
366 oce_log(dev, CE_WARN, MOD_CONFIG,
367 "0x%x soft_reset"
368 "bit asserted[1]. Reset failed",
369 soft_rst.dw0);
370 return (DDI_FAILURE);
371 }
372
373 return (oce_POST(dev));
374 } /* oce_pci_soft_reset */
375
376
377 static int lancer_wait_ready(struct oce_dev *dev)
378 {
379 uint32_t sliport_status;
380 int status = 0, i;
381
382 for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
383 sliport_status = OCE_DB_READ32(dev, SLIPORT_STATUS_OFFSET);
384 if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
385 DDI_FM_OK) {
386 ddi_fm_service_impact(dev->dip,
387 DDI_SERVICE_DEGRADED);
388 return (EIO);
389 }
390 if (sliport_status & SLIPORT_STATUS_RDY_MASK)
391 break;
392 drv_usecwait(20000);
393 }
394
395 if (i == SLIPORT_READY_TIMEOUT)
396 status = DDI_FAILURE;
397
398 return (status);
399 }
400
401 static int lancer_test_and_set_rdy_state(struct oce_dev *dev)
402 {
403 int status;
404 uint32_t sliport_status, err, reset_needed;
405 status = lancer_wait_ready(dev);
406 if (!status) {
407 sliport_status = OCE_DB_READ32(dev, SLIPORT_STATUS_OFFSET);
408 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
409 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
410 return (EIO);
411 }
412 err = sliport_status & SLIPORT_STATUS_ERR_MASK;
413 reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK;
414 if (err && reset_needed) {
415 OCE_DB_WRITE32(dev, SLIPORT_CONTROL_OFFSET,
416 SLI_PORT_CONTROL_IP_MASK);
417 if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
418 DDI_FM_OK) {
419 ddi_fm_service_impact(dev->dip,
420 DDI_SERVICE_DEGRADED);
421 return (EIO);
422 }
423 /* check adapter has corrected the error */
424 status = lancer_wait_ready(dev);
425 sliport_status = OCE_DB_READ32(dev,
426 SLIPORT_STATUS_OFFSET);
427 if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
428 DDI_FM_OK) {
429 ddi_fm_service_impact(dev->dip,
430 DDI_SERVICE_DEGRADED);
431 return (EIO);
432 }
433 sliport_status &= (SLIPORT_STATUS_ERR_MASK |
434 SLIPORT_STATUS_RN_MASK);
435 if (status || sliport_status)
436 status = -1;
437 } else if (err || reset_needed) {
438 status = DDI_FAILURE;
439 }
440 }
441 return (status);
442 }
443
444 /*
445 * function to trigger a POST on the Lancer device
446 *
447 * dev - software handle to the device
448 *
449 */
450 int
451 oce_lancer_POST(struct oce_dev *dev)
452 {
453 int status = 0;
454 int sem = 0;
455 int stage = 0;
456 int timeout = 0;
457
458 status = lancer_test_and_set_rdy_state(dev);
459 if (status != 0)
460 return (DDI_FAILURE);
461
462 do {
463 sem = OCE_DB_READ32(dev, MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
464 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
465 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
466 return (EIO);
467 }
468 stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
469
470 if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) &
471 EP_SEMAPHORE_POST_ERR_MASK) {
472 oce_log(dev, CE_WARN, MOD_CONFIG,
473 "POST error; stage=0x%x\n", stage);
474 return (DDI_FAILURE);
475 } else if (stage != POST_STAGE_ARMFW_READY) {
476 drv_usecwait(1000);
477 } else {
478 return (0);
479 }
480 } while (timeout++ < 1000);
481 oce_log(dev, CE_WARN, MOD_CONFIG,
482 "POST timeout; stage=0x%x\n", stage);
483 return (DDI_FAILURE);
484
485 } /* oce_lancer_POST */
486
487 /*
488 * function to trigger a POST on the BE device
489 *
490 * dev - software handle to the device
491 *
492 */
493 int
494 oce_be_POST(struct oce_dev *dev)
495 {
496 mpu_ep_semaphore_t post_status;
497 clock_t tmo;
498 clock_t earlier = ddi_get_lbolt();
499
500 /* read semaphore CSR */
501 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
502 if (oce_fm_check_acc_handle(dev, dev->csr_handle) != DDI_FM_OK) {
503 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
504 return (DDI_FAILURE);
505 }
506 /* if host is ready then wait for fw ready else send POST */
507 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
508 post_status.bits.stage = POST_STAGE_CHIP_RESET;
509 OCE_CSR_WRITE32(dev, MPU_EP_SEMAPHORE, post_status.dw0);
510 if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
511 DDI_FM_OK) {
512 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
513 return (DDI_FAILURE);
514 }
515 }
522 break;
523 }
524
525 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
526 if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
527 DDI_FM_OK) {
528 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
529 return (DDI_FAILURE);
530 }
531 if (post_status.bits.error) {
532 oce_log(dev, CE_WARN, MOD_CONFIG,
533 "0x%x POST ERROR!!", post_status.dw0);
534 return (DDI_FAILURE);
535 }
536 if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
537 return (DDI_SUCCESS);
538
539 drv_usecwait(100);
540 }
541 return (DDI_FAILURE);
542 } /* oce_be_POST */
543
544 /*
545 * function to trigger a POST on the device
546 *
547 * dev - software handle to the device
548 *
549 */
550 int
551 oce_POST(struct oce_dev *dev)
552 {
553 int ret = 0;
554
555 if (LANCER_CHIP(dev)) {
556 ret = oce_lancer_POST(dev);
557 } else {
558 ret = oce_be_POST(dev);
559 }
560
561 return (ret);
562 }
563
564 /*
565 * function to modify register access attributes corresponding to the
566 * FM capabilities configured by the user
567 *
568 * fm_caps - fm capability configured by the user and accepted by the driver
569 */
570 void
571 oce_set_reg_fma_flags(int fm_caps)
572 {
573 if (fm_caps == DDI_FM_NOT_CAPABLE) {
574 return;
575 }
576 if (DDI_FM_ACC_ERR_CAP(fm_caps)) {
577 reg_accattr.devacc_attr_access = DDI_FLAGERR_ACC;
578 } else {
579 reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC;
580 }
581 } /* oce_set_fma_flags */
582
583
584 int
585 oce_create_nw_interface(struct oce_dev *dev, oce_group_t *grp, uint32_t mode)
586 {
587 int ret;
588 uint32_t cap_flags, en_flags;
589
590 cap_flags = MBX_RX_IFACE_FLAGS_UNTAGGED;
591 en_flags = MBX_RX_IFACE_FLAGS_UNTAGGED;
592
593 /* first/default group receives broadcast and mcast pkts */
594 if (grp->grp_num == 0) {
595 cap_flags |= MBX_RX_IFACE_FLAGS_BROADCAST |
596 MBX_RX_IFACE_FLAGS_MCAST_PROMISCUOUS |
597 MBX_RX_IFACE_FLAGS_PROMISCUOUS |
598 MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS |
599 MBX_RX_IFACE_FLAGS_MCAST;
600
601 en_flags |= MBX_RX_IFACE_FLAGS_BROADCAST |
602 MBX_RX_IFACE_FLAGS_MCAST;
603
604
605 cap_flags |= MBX_RX_IFACE_FLAGS_PASS_L3L4;
606 en_flags |= MBX_RX_IFACE_FLAGS_PASS_L3L4;
607 if (grp->rss_enable) {
608 cap_flags |= MBX_RX_IFACE_FLAGS_RSS;
609 en_flags |= MBX_RX_IFACE_FLAGS_RSS;
610 }
611 }
612
613 if (grp->grp_num == 0) {
614 ret = oce_if_create(dev, cap_flags, en_flags,
615 0, NULL,
616 (uint32_t *)&grp->if_id, mode);
617 /* copy default if_id into dev */
618 dev->if_id = grp->if_id;
619
620 } else {
621 ret = oce_if_create(dev, cap_flags, en_flags,
622 0, NULL, (uint32_t *)&grp->if_id, mode);
623 }
624 if (ret != 0) {
625 oce_log(dev, CE_WARN, MOD_CONFIG,
626 "Interface creation failed for group "
627 "instance %d: 0x%x", grp->grp_num, ret);
628 return (ret);
629 }
630
631 /* Enable VLAN Promisc on HW */
632 ret = oce_config_vlan(dev, (uint8_t)grp->if_id,
633 NULL, 0, B_TRUE, B_TRUE, mode);
634 if (ret != 0) {
635 oce_log(dev, CE_WARN, MOD_CONFIG,
636 "Config vlan failed: 0x%x", ret);
637 oce_delete_nw_interface(dev, grp, mode);
638 return (ret);
639 }
640 return (0);
641 }
642
643 void
644 oce_delete_nw_interface(struct oce_dev *dev, oce_group_t *grp, uint32_t mode)
645 {
646 char itbl[OCE_ITBL_SIZE] = {0};
647 char hkey[OCE_HKEY_SIZE] = {0};
648 int ret = 0;
649
650 if (grp->rss_enable) {
651 ret = oce_config_rss(dev, grp->if_id, hkey,
652 itbl, OCE_ITBL_SIZE, RSS_ENABLE_NONE, B_FALSE, mode);
653
654 if (ret != DDI_SUCCESS) {
655 oce_log(dev, CE_NOTE, MOD_CONFIG,
656 "Failed to Disable RSS if_id=%d, ret=0x%x",
657 grp->if_id, ret);
658 }
659 }
660 ret = oce_if_del(dev, (uint8_t)grp->if_id, mode);
661 if (ret != DDI_SUCCESS)
662 oce_log(dev, CE_NOTE, MOD_CONFIG,
663 "Failed to delete nw i/f gidx =%d if_id = 0x%x ret=0x%x",
664 grp->grp_num, grp->if_id, ret);
665 }
666
667 void
668 oce_group_create_itbl(oce_group_t *grp, char *itbl)
669 {
670 int i;
671 oce_ring_t *rss_queuep = &grp->ring[1];
672 /* fill the indirection table rq 0 is default queue */
673 for (i = 0; i < OCE_ITBL_SIZE; i++) {
674 itbl[i] = rss_queuep[i % (grp->num_rings - 1)].rx->rss_cpuid;
675 }
676 }
677
678
679 int
680 oce_hw_init(struct oce_dev *dev)
681 {
682 int ret;
683 struct mac_address_format mac_addr;
684
685 ret = oce_POST(dev);
686 if (ret != DDI_SUCCESS) {
687 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
688 "!!!HW POST1 FAILED");
689 /* ADD FM FAULT */
690 return (DDI_FAILURE);
691 }
692 /* create bootstrap mailbox */
693 ret = oce_alloc_dma_buffer(dev, &dev->bmbx,
694 sizeof (struct oce_bmbx), NULL, DDI_DMA_CONSISTENT|DDI_DMA_RDWR);
695 if (ret != DDI_SUCCESS) {
696 oce_log(dev, CE_WARN, MOD_CONFIG,
697 "Failed to allocate bmbx: 0x%x", ret);
698 return (DDI_FAILURE);
699 }
700
701 ret = oce_reset_fun(dev);
702 if (ret != 0) {
703 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
704 "!!!FUNCTION RESET FAILED");
705 goto init_fail;
706 }
707
708 /* reset the Endianess of BMBX */
709 ret = oce_mbox_init(dev);
710 if (ret != 0) {
711 oce_log(dev, CE_WARN, MOD_CONFIG,
712 "Mailbox initialization failed with 0x%x", ret);
713 goto init_fail;
714 }
715
716 /* read the firmware version */
717 ret = oce_get_fw_version(dev, MBX_BOOTSTRAP);
718 if (ret != 0) {
719 oce_log(dev, CE_WARN, MOD_CONFIG,
720 "Firmaware version read failed with 0x%x", ret);
721 goto init_fail;
722 }
723
724 /* read the fw config */
725 ret = oce_get_fw_config(dev, MBX_BOOTSTRAP);
726 if (ret != 0) {
727 oce_log(dev, CE_WARN, MOD_CONFIG,
728 "Firmware configuration read failed with %d", ret);
729 goto init_fail;
730 }
731
732 /* read the Factory MAC address */
733 ret = oce_read_mac_addr(dev, 0, 1,
734 MAC_ADDRESS_TYPE_NETWORK, &mac_addr, MBX_BOOTSTRAP);
735 if (ret != 0) {
736 oce_log(dev, CE_WARN, MOD_CONFIG,
737 "MAC address read failed with 0x%x", ret);
738 goto init_fail;
739 }
740 bcopy(&mac_addr.mac_addr[0], &dev->mac_addr[0], ETHERADDRL);
741
742 if (!LANCER_CHIP(dev)) {
743 /* cache the ue mask registers for ue detection */
744 dev->ue_mask_lo = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_LO_MASK);
745 dev->ue_mask_hi = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_HI_MASK);
746 }
747
748 return (DDI_SUCCESS);
749 init_fail:
750 oce_hw_fini(dev);
751 return (DDI_FAILURE);
752 }
753 void
754 oce_hw_fini(struct oce_dev *dev)
755 {
756 (void) oce_mbox_fini(dev);
757 oce_free_dma_buffer(dev, &dev->bmbx);
758 }
759
760 boolean_t
761 oce_check_ue(struct oce_dev *dev)
762 {
763 uint32_t ue_lo;
764 uint32_t ue_hi;
765
766 /* check for the Hardware unexpected error */
767 ue_lo = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_LO);
768 ue_hi = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_HI);
769
770 if ((~dev->ue_mask_lo & ue_lo) ||
771 (~dev->ue_mask_hi & ue_hi)) {
772 /* Unrecoverable error detected */
773 oce_log(dev, CE_WARN, MOD_CONFIG,
774 "Hardware UE Detected: "
775 "UE_LOW:%08x"
776 "UE_HI:%08x "
777 "UE_MASK_LO:%08x "
778 "UE_MASK_HI:%08x",
779 ue_lo, ue_hi,
780 dev->ue_mask_lo,
781 dev->ue_mask_hi);
782 return (B_TRUE);
783 }
784 return (B_FALSE);
785 }
|