Print this page
NEX-1890 update oce from source provided by Emulex
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/oce/oce_gld.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/oce/oce_gld.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 -/* Copyright © 2003-2011 Emulex. All rights reserved. */
22 +/*
23 + * Copyright (c) 2009-2012 Emulex. All rights reserved.
24 + * Use is subject to license terms.
25 + */
23 26
27 +
28 +
24 29 /*
25 30 * Source file containing the implementation of the driver entry points
26 31 * and related helper functions
27 32 */
28 33
29 34 #include <oce_impl.h>
30 35 #include <oce_ioctl.h>
31 36
32 -/* array of properties supported by this driver */
33 -char *oce_priv_props[] = {
34 - "_tx_ring_size",
35 - "_tx_bcopy_limit",
36 - "_rx_ring_size",
37 - "_rx_bcopy_limit",
38 - NULL
39 -};
40 -
41 -extern int pow10[];
42 -
43 37 /* ---[ static function declarations ]----------------------------------- */
44 38 static int oce_set_priv_prop(struct oce_dev *dev, const char *name,
45 39 uint_t size, const void *val);
46 40
47 41 static int oce_get_priv_prop(struct oce_dev *dev, const char *name,
48 42 uint_t size, void *val);
49 43
50 44 /* ---[ GLD entry points ]----------------------------------------------- */
51 45 int
52 46 oce_m_start(void *arg)
53 47 {
54 48 struct oce_dev *dev = arg;
55 - int ret;
49 + int i;
56 50
57 51 mutex_enter(&dev->dev_lock);
58 52
59 53 if (dev->state & STATE_MAC_STARTED) {
60 54 mutex_exit(&dev->dev_lock);
61 55 return (0);
62 56 }
63 57
64 58 if (dev->suspended) {
65 59 mutex_exit(&dev->dev_lock);
66 60 return (EIO);
67 61 }
68 - ret = oce_start(dev);
69 - if (ret != DDI_SUCCESS) {
62 +
63 + /* allocate Tx buffers */
64 + if (oce_init_tx(dev) != DDI_SUCCESS) {
70 65 mutex_exit(&dev->dev_lock);
71 - return (EIO);
66 + oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
67 + "Failed to init rings");
68 + return (DDI_FAILURE);
72 69 }
73 70
71 + if (oce_start(dev) != DDI_SUCCESS) {
72 + oce_fini_tx(dev);
73 + mutex_exit(&dev->dev_lock);
74 + return (EIO);
75 + }
74 76 dev->state |= STATE_MAC_STARTED;
75 - mutex_exit(&dev->dev_lock);
76 77
78 + /* initialise the group locks */
79 + for (i = 0; i < dev->num_rx_groups; i++) {
80 + mutex_init(&dev->rx_group[i].grp_lock, NULL, MUTEX_DRIVER,
81 + DDI_INTR_PRI(dev->intr_pri));
82 + }
77 83
84 + mutex_exit(&dev->dev_lock);
85 + oce_enable_wd_timer(dev);
78 86 return (DDI_SUCCESS);
79 87 }
80 88
89 +void
90 +oce_start_eqs(struct oce_dev *dev)
91 +{
92 + int qidx = 0;
93 +
94 + for (qidx = 0; qidx < dev->neqs; qidx++) {
95 + mutex_enter(&dev->eq[qidx].lock);
96 + oce_arm_eq(dev, dev->eq[qidx].eq_id, 0, B_TRUE, B_FALSE);
97 + dev->eq[qidx].qstate = QSTARTED;
98 + mutex_exit(&dev->eq[qidx].lock);
99 + }
100 +}
101 +
102 +void
103 +oce_stop_eqs(struct oce_dev *dev)
104 +{
105 + int qidx = 0;
106 +
107 + for (qidx = 0; qidx < dev->neqs; qidx++) {
108 + mutex_enter(&dev->eq[qidx].lock);
109 + oce_arm_eq(dev, dev->eq[qidx].eq_id, 0, B_FALSE, B_FALSE);
110 + dev->eq[qidx].qstate = QSTOPPED;
111 + mutex_exit(&dev->eq[qidx].lock);
112 + }
113 +}
81 114 int
82 115 oce_start(struct oce_dev *dev)
83 116 {
84 117 int qidx = 0;
85 - struct link_status link = {0};
86 118
87 - /* get link status */
88 - (void) oce_get_link_status(dev, &link);
119 + /* disable the interrupts */
120 + if (!LANCER_CHIP(dev))
121 + oce_chip_di(dev);
89 122
90 - dev->link_status = (link.logical_link_status == NTWK_LOGICAL_LINK_UP) ?
91 - LINK_STATE_UP : LINK_STATE_DOWN;
123 + /* set default flow control */
124 + (void) oce_set_flow_control(dev, dev->flow_control, MBX_BOOTSTRAP);
125 + (void) oce_set_promiscuous(dev, dev->promisc, MBX_BOOTSTRAP);
92 126
93 - dev->link_speed = link.qos_link_speed ? link.qos_link_speed * 10 :
94 - pow10[link.mac_speed];
127 + if (oce_ei(dev) != DDI_SUCCESS) {
128 + return (DDI_FAILURE);
129 + }
95 130
96 - mac_link_update(dev->mac_handle, dev->link_status);
131 + if (oce_create_queues(dev) != DDI_SUCCESS) {
132 + goto cleanup_handler;
133 + }
97 134
98 - for (qidx = 0; qidx < dev->nwqs; qidx++) {
99 - (void) oce_start_wq(dev->wq[qidx]);
135 + for (qidx = 0; qidx < dev->tx_rings; qidx++) {
136 + mac_ring_intr_set(dev->default_tx_rings[qidx].tx->handle,
137 + dev->htable[dev->default_tx_rings[qidx].tx->cq->eq->idx]);
138 + (void) oce_start_wq(dev->default_tx_rings[qidx].tx);
100 139 }
101 - for (qidx = 0; qidx < dev->nrqs; qidx++) {
102 - (void) oce_start_rq(dev->rq[qidx]);
140 +
141 + if (oce_create_mcc_queue(dev) != DDI_SUCCESS) {
142 + goto delete_queues;
103 143 }
104 144 (void) oce_start_mq(dev->mq);
105 - /* enable interrupts */
106 - oce_ei(dev);
145 +
146 + dev->state |= STATE_INTR_ENABLED;
147 +
148 + if (!LANCER_CHIP(dev))
149 + oce_chip_ei(dev);
150 +
107 151 /* arm the eqs */
108 - for (qidx = 0; qidx < dev->neqs; qidx++) {
109 - oce_arm_eq(dev, dev->eq[qidx]->eq_id, 0, B_TRUE, B_FALSE);
152 + oce_start_eqs(dev);
153 +
154 + /* get link status */
155 + if (oce_get_link_status(dev, &dev->link_status, &dev->link_speed,
156 + (uint8_t *)&dev->link_duplex, 1, MBX_ASYNC_MQ) != DDI_SUCCESS) {
157 + (void) oce_get_link_status(dev, &dev->link_status,
158 + &dev->link_speed, (uint8_t *)&dev->link_duplex,
159 + 0, MBX_ASYNC_MQ);
110 160 }
111 - /* TODO update state */
161 + oce_log(dev, CE_NOTE, MOD_CONFIG, "link speed %d "
162 + "link status %d", dev->link_speed, dev->link_status);
163 +
164 + mac_link_update(dev->mac_handle, dev->link_status);
112 165 return (DDI_SUCCESS);
166 +
167 +delete_queues:
168 + oce_delete_queues(dev);
169 +cleanup_handler:
170 + (void) oce_di(dev);
171 + return (DDI_FAILURE);
113 172 } /* oce_start */
114 173
115 174
116 175 void
117 176 oce_m_stop(void *arg)
118 177 {
119 178 struct oce_dev *dev = arg;
179 + int i;
120 180
121 - /* disable interrupts */
122 -
123 181 mutex_enter(&dev->dev_lock);
124 182 if (dev->suspended) {
125 183 mutex_exit(&dev->dev_lock);
126 184 return;
127 185 }
128 - dev->state |= STATE_MAC_STOPPING;
186 +
187 + dev->state &= ~STATE_MAC_STARTED;
129 188 oce_stop(dev);
130 - dev->state &= ~(STATE_MAC_STOPPING | STATE_MAC_STARTED);
189 +
190 + /* free Tx buffers */
191 + oce_fini_tx(dev);
192 +
193 + for (i = 0; i < dev->rx_rings; i++) {
194 + while (dev->rq[i].pending > 0) {
195 + oce_log(dev, CE_NOTE, MOD_CONFIG,
196 + "%d pending buffers on rq %p\n",
197 + dev->rq[i].pending, (void *)&dev->rq[i]);
198 + drv_usecwait(10 * 1000);
199 + }
200 + }
201 +
202 + /* destroy group locks */
203 + for (i = 0; i < dev->num_rx_groups; i++) {
204 + mutex_destroy(&dev->rx_group[i].grp_lock);
205 + }
206 +
131 207 mutex_exit(&dev->dev_lock);
208 + oce_disable_wd_timer(dev);
132 209 }
210 +
211 +
133 212 /* called with Tx/Rx comp locks held */
134 213 void
135 214 oce_stop(struct oce_dev *dev)
136 215 {
137 216 int qidx;
217 +
218 + dev->state |= STATE_MAC_STOPPING;
219 +
138 220 /* disable interrupts */
139 - oce_di(dev);
221 + (void) oce_di(dev);
222 + oce_stop_eqs(dev);
223 + dev->state &= (~STATE_INTR_ENABLED);
224 +
140 225 for (qidx = 0; qidx < dev->nwqs; qidx++) {
141 - mutex_enter(&dev->wq[qidx]->tx_lock);
226 + mac_ring_intr_set(dev->default_tx_rings[qidx].tx->handle, NULL);
227 + mutex_enter(&dev->wq[qidx].tx_lock);
142 228 }
143 229 mutex_enter(&dev->mq->lock);
144 - /* complete the pending Tx */
145 - for (qidx = 0; qidx < dev->nwqs; qidx++)
146 - oce_clean_wq(dev->wq[qidx]);
230 +
231 + for (qidx = 0; qidx < dev->tx_rings; qidx++) {
232 + /* stop and flush the Tx */
233 + (void) oce_clean_wq(dev->default_tx_rings[qidx].tx);
234 + }
235 +
236 + /* Free the pending commands */
237 + oce_clean_mq(dev->mq);
238 +
147 239 /* Release all the locks */
148 240 mutex_exit(&dev->mq->lock);
149 241 for (qidx = 0; qidx < dev->nwqs; qidx++)
150 - mutex_exit(&dev->wq[qidx]->tx_lock);
242 + mutex_exit(&dev->wq[qidx].tx_lock);
243 +
151 244 if (dev->link_status == LINK_STATE_UP) {
152 245 dev->link_status = LINK_STATE_UNKNOWN;
153 246 mac_link_update(dev->mac_handle, dev->link_status);
154 247 }
155 248
249 + oce_delete_mcc_queue(dev);
250 + oce_delete_queues(dev);
251 +
252 + dev->state &= ~STATE_MAC_STOPPING;
156 253 } /* oce_stop */
157 254
255 +
158 256 int
159 257 oce_m_multicast(void *arg, boolean_t add, const uint8_t *mca)
160 258 {
161 259 struct oce_dev *dev = (struct oce_dev *)arg;
162 260 struct ether_addr *mca_drv_list;
163 261 struct ether_addr mca_hw_list[OCE_MAX_MCA];
164 262 uint16_t new_mcnt = dev->num_mca;
165 263 int ret;
166 264 int i;
167 265
168 - /* check the address */
169 - if ((mca[0] & 0x1) == 0) {
170 - return (EINVAL);
171 - }
172 266 /* Allocate the local array for holding the addresses temporarily */
173 267 bzero(&mca_hw_list, sizeof (&mca_hw_list));
174 268 mca_drv_list = &dev->multi_cast[0];
175 269
176 270 DEV_LOCK(dev);
177 271 if (add) {
178 272 /* check if we exceeded hw max supported */
179 273 if (new_mcnt < OCE_MAX_MCA) {
180 274 /* copy entire dev mca to the mbx */
181 275 bcopy((void*)mca_drv_list,
182 276 (void*)mca_hw_list,
183 277 (dev->num_mca * sizeof (struct ether_addr)));
184 278 /* Append the new one to local list */
185 279 bcopy(mca, &mca_hw_list[dev->num_mca],
186 280 sizeof (struct ether_addr));
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
187 281 }
188 282 new_mcnt++;
189 283 } else {
190 284 struct ether_addr *hwlistp = &mca_hw_list[0];
191 285 for (i = 0; i < dev->num_mca; i++) {
192 286 /* copy only if it does not match */
193 287 if (bcmp((mca_drv_list + i), mca, ETHERADDRL)) {
194 288 bcopy(mca_drv_list + i, hwlistp,
195 289 ETHERADDRL);
196 290 hwlistp++;
197 - } else {
198 - new_mcnt--;
199 291 }
200 292 }
293 + /* Decrement the count */
294 + new_mcnt--;
201 295 }
202 296
203 297 if (dev->suspended) {
204 298 goto finish;
205 299 }
206 300 if (new_mcnt > OCE_MAX_MCA) {
207 301 ret = oce_set_multicast_table(dev, dev->if_id, &mca_hw_list[0],
208 - OCE_MAX_MCA, B_TRUE);
302 + OCE_MAX_MCA, B_TRUE, MBX_BOOTSTRAP);
209 303 } else {
210 304 ret = oce_set_multicast_table(dev, dev->if_id,
211 - &mca_hw_list[0], new_mcnt, B_FALSE);
305 + &mca_hw_list[0], new_mcnt, B_FALSE, MBX_BOOTSTRAP);
212 306 }
213 - if (ret != 0) {
307 + if (ret != 0) {
214 308 oce_log(dev, CE_WARN, MOD_CONFIG,
215 - "mcast %s fails", add ? "ADD" : "DEL");
309 + "mcast %s failed 0x%x", add ? "ADD" : "DEL", ret);
216 310 DEV_UNLOCK(dev);
217 311 return (EIO);
218 312 }
219 313 /*
220 314 * Copy the local structure to dev structure
221 315 */
222 316 finish:
223 317 if (new_mcnt && new_mcnt <= OCE_MAX_MCA) {
224 318 bcopy(mca_hw_list, mca_drv_list,
225 319 new_mcnt * sizeof (struct ether_addr));
226 320
227 321 dev->num_mca = (uint16_t)new_mcnt;
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
228 322 }
229 323 DEV_UNLOCK(dev);
230 324 oce_log(dev, CE_NOTE, MOD_CONFIG,
231 325 "mcast %s, addr=%02x:%02x:%02x:%02x:%02x:%02x, num_mca=%d",
232 326 add ? "ADD" : "DEL",
233 327 mca[0], mca[1], mca[2], mca[3], mca[4], mca[5],
234 328 dev->num_mca);
235 329 return (0);
236 330 } /* oce_m_multicast */
237 331
238 -int
239 -oce_m_unicast(void *arg, const uint8_t *uca)
240 -{
241 - struct oce_dev *dev = arg;
242 - int ret;
243 332
244 - DEV_LOCK(dev);
245 - if (dev->suspended) {
246 - bcopy(uca, dev->unicast_addr, ETHERADDRL);
247 - dev->num_smac = 0;
248 - DEV_UNLOCK(dev);
249 - return (DDI_SUCCESS);
250 - }
251 -
252 - /* Delete previous one and add new one */
253 - ret = oce_del_mac(dev, dev->if_id, &dev->pmac_id);
254 - if (ret != DDI_SUCCESS) {
255 - DEV_UNLOCK(dev);
256 - return (EIO);
257 - }
258 - dev->num_smac = 0;
259 - bzero(dev->unicast_addr, ETHERADDRL);
260 -
261 - /* Set the New MAC addr earlier is no longer valid */
262 - ret = oce_add_mac(dev, dev->if_id, uca, &dev->pmac_id);
263 - if (ret != DDI_SUCCESS) {
264 - DEV_UNLOCK(dev);
265 - return (EIO);
266 - }
267 - bcopy(uca, dev->unicast_addr, ETHERADDRL);
268 - dev->num_smac = 1;
269 - DEV_UNLOCK(dev);
270 - return (ret);
271 -} /* oce_m_unicast */
272 -
273 -/*
274 - * Hashing policy for load balancing over the set of TX rings
275 - * available to the driver.
276 - */
277 -mblk_t *
278 -oce_m_send(void *arg, mblk_t *mp)
279 -{
280 - struct oce_dev *dev = arg;
281 - mblk_t *nxt_pkt;
282 - mblk_t *rmp = NULL;
283 - struct oce_wq *wq;
284 -
285 - DEV_LOCK(dev);
286 - if (dev->suspended || !(dev->state & STATE_MAC_STARTED)) {
287 - DEV_UNLOCK(dev);
288 - freemsg(mp);
289 - return (NULL);
290 - }
291 - DEV_UNLOCK(dev);
292 - /*
293 - * Hash to pick a wq
294 - */
295 - wq = oce_get_wq(dev, mp);
296 -
297 - while (mp != NULL) {
298 - /* Save the Pointer since mp will be freed in case of copy */
299 - nxt_pkt = mp->b_next;
300 - mp->b_next = NULL;
301 - /* Hardcode wq since we have only one */
302 - rmp = oce_send_packet(wq, mp);
303 - if (rmp != NULL) {
304 - /* reschedule Tx */
305 - wq->resched = B_TRUE;
306 - oce_arm_cq(dev, wq->cq->cq_id, 0, B_TRUE);
307 - /* restore the chain */
308 - rmp->b_next = nxt_pkt;
309 - break;
310 - }
311 - mp = nxt_pkt;
312 - }
313 - return (rmp);
314 -} /* oce_send */
315 -
316 333 boolean_t
317 334 oce_m_getcap(void *arg, mac_capab_t cap, void *data)
318 335 {
319 336 struct oce_dev *dev = arg;
320 337 boolean_t ret = B_TRUE;
321 338 switch (cap) {
322 339
323 340 case MAC_CAPAB_HCKSUM: {
324 341 uint32_t *csum_flags = u32ptr(data);
325 342 *csum_flags = HCKSUM_ENABLE |
326 343 HCKSUM_INET_FULL_V4 |
327 344 HCKSUM_IPHDRCKSUM;
328 345 break;
329 346 }
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
330 347 case MAC_CAPAB_LSO: {
331 348 mac_capab_lso_t *mcap_lso = (mac_capab_lso_t *)data;
332 349 if (dev->lso_capable) {
333 350 mcap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
334 351 mcap_lso->lso_basic_tcp_ipv4.lso_max = OCE_LSO_MAX_SIZE;
335 352 } else {
336 353 ret = B_FALSE;
337 354 }
338 355 break;
339 356 }
357 + case MAC_CAPAB_RINGS:
358 +
359 + ret = oce_fill_rings_capab(dev, (mac_capab_rings_t *)data);
360 + break;
361 +
340 362 default:
341 363 ret = B_FALSE;
342 364 break;
343 365 }
344 366 return (ret);
345 367 } /* oce_m_getcap */
346 368
347 369 int
348 370 oce_m_setprop(void *arg, const char *name, mac_prop_id_t id,
349 371 uint_t size, const void *val)
350 372 {
351 373 struct oce_dev *dev = arg;
352 374 int ret = 0;
353 375
354 376 DEV_LOCK(dev);
355 377 switch (id) {
356 378 case MAC_PROP_MTU: {
357 379 uint32_t mtu;
358 380
359 381 bcopy(val, &mtu, sizeof (uint32_t));
360 382
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
361 383 if (dev->mtu == mtu) {
362 384 ret = 0;
363 385 break;
364 386 }
365 387
366 388 if (mtu != OCE_MIN_MTU && mtu != OCE_MAX_MTU) {
367 389 ret = EINVAL;
368 390 break;
369 391 }
370 392
393 + if (dev->state & STATE_MAC_STARTED) {
394 + ret = EBUSY;
395 + break;
396 + }
397 +
371 398 ret = mac_maxsdu_update(dev->mac_handle, mtu);
372 399 if (0 == ret) {
373 400 dev->mtu = mtu;
374 401 break;
375 402 }
376 403 break;
377 404 }
378 405
379 406 case MAC_PROP_FLOWCTRL: {
380 407 link_flowctrl_t flowctrl;
381 408 uint32_t fc = 0;
382 409
383 410 bcopy(val, &flowctrl, sizeof (link_flowctrl_t));
384 411
385 412 switch (flowctrl) {
386 413 case LINK_FLOWCTRL_NONE:
387 414 fc = 0;
388 415 break;
389 416
390 417 case LINK_FLOWCTRL_RX:
391 418 fc = OCE_FC_RX;
392 419 break;
393 420
394 421 case LINK_FLOWCTRL_TX:
395 422 fc = OCE_FC_TX;
396 423 break;
397 424
398 425 case LINK_FLOWCTRL_BI:
399 426 fc = OCE_FC_RX | OCE_FC_TX;
400 427 break;
401 428 default:
402 429 ret = EINVAL;
403 430 break;
404 431 } /* switch flowctrl */
405 432
406 433 if (ret)
|
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
407 434 break;
408 435
409 436 if (fc == dev->flow_control)
410 437 break;
411 438
412 439 if (dev->suspended) {
413 440 dev->flow_control = fc;
414 441 break;
415 442 }
416 443 /* call to set flow control */
417 - ret = oce_set_flow_control(dev, fc);
444 + ret = oce_set_flow_control(dev, fc, MBX_ASYNC_MQ);
418 445 /* store the new fc setting on success */
419 446 if (ret == 0) {
420 - dev->flow_control = fc;
447 + dev->flow_control = fc;
421 448 }
422 449 break;
423 450 }
424 451
425 452 case MAC_PROP_PRIVATE:
426 453 ret = oce_set_priv_prop(dev, name, size, val);
427 454 break;
428 455
429 456 default:
430 457 ret = ENOTSUP;
431 458 break;
432 459 } /* switch id */
433 460
434 461 DEV_UNLOCK(dev);
435 462 return (ret);
436 463 } /* oce_m_setprop */
437 464
438 465 int
439 466 oce_m_getprop(void *arg, const char *name, mac_prop_id_t id,
440 467 uint_t size, void *val)
441 468 {
442 469 struct oce_dev *dev = arg;
443 470 uint32_t ret = 0;
444 471
445 472 switch (id) {
446 473 case MAC_PROP_ADV_10GFDX_CAP:
447 474 case MAC_PROP_EN_10GFDX_CAP:
448 475 *(uint8_t *)val = 0x01;
449 476 break;
450 477
451 478 case MAC_PROP_DUPLEX: {
452 479 uint32_t *mode = (uint32_t *)val;
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
453 480
454 481 ASSERT(size >= sizeof (link_duplex_t));
455 482 if (dev->state & STATE_MAC_STARTED)
456 483 *mode = LINK_DUPLEX_FULL;
457 484 else
458 485 *mode = LINK_DUPLEX_UNKNOWN;
459 486 break;
460 487 }
461 488
462 489 case MAC_PROP_SPEED: {
463 - uint64_t *speed = (uint64_t *)val;
464 - struct link_status link = {0};
465 -
466 - ASSERT(size >= sizeof (uint64_t));
467 - *speed = 0;
468 -
469 - if (dev->state & STATE_MAC_STARTED) {
470 - if (dev->link_speed < 0) {
471 - (void) oce_get_link_status(dev, &link);
472 - dev->link_speed = link.qos_link_speed ?
473 - link.qos_link_speed * 10 :
474 - pow10[link.mac_speed];
475 - }
476 -
477 - *speed = dev->link_speed * 1000000ull;
478 - }
490 + uint64_t speed;
491 + speed = dev->link_speed * 1000000ull;
492 + bcopy(&speed, val, sizeof (speed));
479 493 break;
480 494 }
481 495
482 496 case MAC_PROP_FLOWCTRL: {
483 497 link_flowctrl_t *fc = (link_flowctrl_t *)val;
484 498
485 499 ASSERT(size >= sizeof (link_flowctrl_t));
486 500 if (dev->flow_control & OCE_FC_TX &&
487 501 dev->flow_control & OCE_FC_RX)
488 502 *fc = LINK_FLOWCTRL_BI;
489 503 else if (dev->flow_control == OCE_FC_TX)
490 504 *fc = LINK_FLOWCTRL_TX;
491 505 else if (dev->flow_control == OCE_FC_RX)
492 506 *fc = LINK_FLOWCTRL_RX;
493 507 else if (dev->flow_control == 0)
494 508 *fc = LINK_FLOWCTRL_NONE;
495 509 else
496 510 ret = EINVAL;
497 511 break;
498 512 }
499 513
500 514 case MAC_PROP_PRIVATE:
501 515 ret = oce_get_priv_prop(dev, name, size, val);
502 516 break;
503 517
504 518 default:
505 519 ret = ENOTSUP;
506 520 break;
507 521 } /* switch id */
508 522 return (ret);
509 523 } /* oce_m_getprop */
510 524
511 525 void
512 526 oce_m_propinfo(void *arg, const char *name, mac_prop_id_t pr_num,
513 527 mac_prop_info_handle_t prh)
514 528 {
515 529 _NOTE(ARGUNUSED(arg));
516 530
517 531 switch (pr_num) {
518 532 case MAC_PROP_AUTONEG:
519 533 case MAC_PROP_EN_AUTONEG:
520 534 case MAC_PROP_ADV_1000FDX_CAP:
521 535 case MAC_PROP_EN_1000FDX_CAP:
522 536 case MAC_PROP_ADV_1000HDX_CAP:
523 537 case MAC_PROP_EN_1000HDX_CAP:
524 538 case MAC_PROP_ADV_100FDX_CAP:
525 539 case MAC_PROP_EN_100FDX_CAP:
526 540 case MAC_PROP_ADV_100HDX_CAP:
527 541 case MAC_PROP_EN_100HDX_CAP:
528 542 case MAC_PROP_ADV_10FDX_CAP:
529 543 case MAC_PROP_EN_10FDX_CAP:
530 544 case MAC_PROP_ADV_10HDX_CAP:
531 545 case MAC_PROP_EN_10HDX_CAP:
532 546 case MAC_PROP_ADV_100T4_CAP:
533 547 case MAC_PROP_EN_100T4_CAP:
534 548 case MAC_PROP_ADV_10GFDX_CAP:
535 549 case MAC_PROP_EN_10GFDX_CAP:
536 550 case MAC_PROP_SPEED:
537 551 case MAC_PROP_DUPLEX:
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
538 552 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
539 553 break;
540 554
541 555 case MAC_PROP_MTU:
542 556 mac_prop_info_set_range_uint32(prh, OCE_MIN_MTU, OCE_MAX_MTU);
543 557 break;
544 558
545 559 case MAC_PROP_PRIVATE: {
546 560 char valstr[64];
547 561 int value;
562 + uint_t perm = MAC_PROP_PERM_READ;
548 563
549 - if (strcmp(name, "_tx_ring_size") == 0) {
564 + bzero(valstr, sizeof (valstr));
565 + if (strcmp(name, "_tx_rings") == 0) {
566 + value = OCE_DEFAULT_WQS;
567 + } else if (strcmp(name, "_tx_ring_size") == 0) {
550 568 value = OCE_DEFAULT_TX_RING_SIZE;
569 + perm = MAC_PROP_PERM_RW;
570 + } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
571 + value = OCE_DEFAULT_TX_BCOPY_LIMIT;
572 + perm = MAC_PROP_PERM_RW;
573 + } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
574 + value = OCE_DEFAULT_TX_RECLAIM_THRESHOLD;
575 + perm = MAC_PROP_PERM_RW;
576 + } else if (strcmp(name, "_rx_rings") == 0) {
577 + value = OCE_DEFAULT_RQS;
578 + } else if (strcmp(name, "_rx_rings_per_group") == 0) {
579 + value = OCE_DEF_RING_PER_GROUP;
551 580 } else if (strcmp(name, "_rx_ring_size") == 0) {
552 581 value = OCE_DEFAULT_RX_RING_SIZE;
553 - } else {
582 + } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
583 + value = OCE_DEFAULT_RX_BCOPY_LIMIT;
584 + perm = MAC_PROP_PERM_RW;
585 + } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
586 + value = OCE_DEFAULT_RX_PKTS_PER_INTR;
587 + perm = MAC_PROP_PERM_RW;
588 + } else if (strcmp(name, "_log_level") == 0) {
589 + value = OCE_DEFAULT_LOG_SETTINGS;
590 + perm = MAC_PROP_PERM_RW;
591 + } else
554 592 return;
555 - }
556 593
557 594 (void) snprintf(valstr, sizeof (valstr), "%d", value);
558 595 mac_prop_info_set_default_str(prh, valstr);
559 - mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
596 + mac_prop_info_set_perm(prh, perm);
560 597 break;
561 598 }
562 599 }
563 600 } /* oce_m_propinfo */
564 601
565 602 /*
566 603 * function to handle dlpi streams message from GLDv3 mac layer
567 604 */
568 605 void
569 606 oce_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
570 607 {
571 608 struct oce_dev *dev = arg;
572 609 struct iocblk *iocp;
573 610 int cmd;
574 611 uint32_t payload_length;
575 612 int ret;
576 613
577 614 iocp = (struct iocblk *)voidptr(mp->b_rptr);
578 615 iocp->ioc_error = 0;
579 616 cmd = iocp->ioc_cmd;
580 617
581 618 DEV_LOCK(dev);
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
582 619 if (dev->suspended) {
583 620 miocnak(wq, mp, 0, EINVAL);
584 621 DEV_UNLOCK(dev);
585 622 return;
586 623 }
587 624 DEV_UNLOCK(dev);
588 625
589 626 switch (cmd) {
590 627
591 628 case OCE_ISSUE_MBOX: {
592 - ret = oce_issue_mbox(dev, wq, mp, &payload_length);
629 + ret = oce_issue_mbox_passthru(dev, wq, mp, &payload_length);
593 630 miocack(wq, mp, payload_length, ret);
594 631 break;
595 632 }
596 633 case OCE_QUERY_DRIVER_DATA: {
597 634 struct oce_driver_query *drv_query =
598 635 (struct oce_driver_query *)(void *)mp->b_cont->b_rptr;
599 636
600 637 /* if the driver version does not match bail */
601 638 if (drv_query->version != OCN_VERSION_SUPPORTED) {
602 639 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
603 640 "One Connect version mismatch");
604 641 miocnak(wq, mp, 0, ENOTSUP);
605 642 break;
606 643 }
607 644
608 645 /* fill the return values */
609 646 bcopy(OCE_MOD_NAME, drv_query->driver_name,
610 647 (sizeof (OCE_MOD_NAME) > 32) ?
611 648 31 : sizeof (OCE_MOD_NAME));
612 649 drv_query->driver_name[31] = '\0';
613 650
614 651 bcopy(OCE_VERSION, drv_query->driver_version,
615 652 (sizeof (OCE_VERSION) > 32) ? 31 :
616 653 sizeof (OCE_VERSION));
617 654 drv_query->driver_version[31] = '\0';
618 655
619 656 if (dev->num_smac == 0) {
620 657 drv_query->num_smac = 1;
621 658 bcopy(dev->mac_addr, drv_query->smac_addr[0],
622 659 ETHERADDRL);
623 660 } else {
624 661 drv_query->num_smac = dev->num_smac;
625 662 bcopy(dev->unicast_addr, drv_query->smac_addr[0],
626 663 ETHERADDRL);
627 664 }
628 665
629 666 bcopy(dev->mac_addr, drv_query->pmac_addr, ETHERADDRL);
630 667
631 668 payload_length = sizeof (struct oce_driver_query);
632 669 miocack(wq, mp, payload_length, 0);
633 670 break;
634 671 }
635 672
636 673 default:
637 674 miocnak(wq, mp, 0, ENOTSUP);
638 675 break;
639 676 }
640 677 } /* oce_m_ioctl */
641 678
642 679 int
643 680 oce_m_promiscuous(void *arg, boolean_t enable)
644 681 {
645 682 struct oce_dev *dev = arg;
646 683 int ret = 0;
647 684
648 685 DEV_LOCK(dev);
649 686
650 687 if (dev->promisc == enable) {
651 688 DEV_UNLOCK(dev);
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
652 689 return (ret);
653 690 }
654 691
655 692 if (dev->suspended) {
656 693 /* remember the setting */
657 694 dev->promisc = enable;
658 695 DEV_UNLOCK(dev);
659 696 return (ret);
660 697 }
661 698
662 - ret = oce_set_promiscuous(dev, enable);
663 - if (ret == DDI_SUCCESS)
699 + ret = oce_set_promiscuous(dev, enable, MBX_ASYNC_MQ);
700 + if (ret == DDI_SUCCESS) {
664 701 dev->promisc = enable;
702 + if (!(enable)) {
703 + struct ether_addr *mca_drv_list;
704 + mca_drv_list = &dev->multi_cast[0];
705 + if (dev->num_mca > OCE_MAX_MCA) {
706 + ret = oce_set_multicast_table(dev, dev->if_id,
707 + &mca_drv_list[0], OCE_MAX_MCA, B_TRUE,
708 + MBX_ASYNC_MQ);
709 + } else {
710 + ret = oce_set_multicast_table(dev, dev->if_id,
711 + &mca_drv_list[0], dev->num_mca, B_FALSE,
712 + MBX_ASYNC_MQ);
713 + }
714 + }
715 + }
665 716 DEV_UNLOCK(dev);
666 717 return (ret);
667 718 } /* oce_m_promiscuous */
668 719
669 720 /*
670 721 * function to set a private property.
671 722 * Called from the set_prop GLD entry point
672 723 *
673 724 * dev - sofware handle to the device
674 725 * name - string containing the property name
675 726 * size - length of the string in name
676 727 * val - pointer to a location where the value to set is stored
677 728 *
678 729 * return EINVAL => invalid value in val 0 => success
679 730 */
680 731 static int
681 732 oce_set_priv_prop(struct oce_dev *dev, const char *name,
682 733 uint_t size, const void *val)
683 734 {
684 - int ret = ENOTSUP;
735 + int ret = EINVAL;
685 736 long result;
686 737
687 738 _NOTE(ARGUNUSED(size));
688 739
689 740 if (NULL == val) {
690 - ret = EINVAL;
691 - return (ret);
741 + return (EINVAL);
692 742 }
693 -
694 - if (strcmp(name, "_tx_bcopy_limit") == 0) {
695 - (void) ddi_strtol(val, (char **)NULL, 0, &result);
696 - if (result <= OCE_WQ_BUF_SIZE) {
743 + (void) ddi_strtol(val, (char **)NULL, 0, &result);
744 + if (strcmp(name, "_tx_ring_size") == 0) {
745 + if (result <= SIZE_2K) {
746 + if (dev->tx_ring_size != result) {
747 + dev->tx_ring_size = (uint32_t)result;
748 + }
749 + ret = 0;
750 + }
751 + } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
752 + if (result <= SIZE_2K) {
697 753 if (result != dev->tx_bcopy_limit)
698 754 dev->tx_bcopy_limit = (uint32_t)result;
699 755 ret = 0;
700 - } else {
701 - ret = EINVAL;
702 756 }
703 - }
704 - if (strcmp(name, "_rx_bcopy_limit") == 0) {
705 - (void) ddi_strtol(val, (char **)NULL, 0, &result);
706 - if (result <= OCE_RQ_BUF_SIZE) {
707 - if (result != dev->rx_bcopy_limit)
757 + } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
758 + if (result <= dev->tx_ring_size) {
759 + if (dev->tx_reclaim_threshold != result) {
760 + dev->tx_reclaim_threshold = (uint32_t)result;
761 + }
762 + ret = 0;
763 + }
764 + } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
765 + if (result <= dev->mtu) {
766 + if (dev->rx_bcopy_limit != result) {
708 767 dev->rx_bcopy_limit = (uint32_t)result;
768 + }
709 769 ret = 0;
710 - } else {
711 - ret = EINVAL;
712 770 }
771 + } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
772 + if (result <= dev->rx_ring_size) {
773 + if (dev->rx_pkt_per_intr != result) {
774 + dev->rx_pkt_per_intr = (uint32_t)result;
775 + }
776 + ret = 0;
777 + }
778 + } else if (strcmp(name, "_log_level") == 0) {
779 + if (result <= OCE_MAX_LOG_SETTINGS) {
780 + /* derive from the loglevel */
781 + dev->severity = (uint16_t)(result & 0xffff);
782 + dev->mod_mask = (uint16_t)(result >> 16);
783 + }
784 + ret = 0;
713 785 }
714 786
715 787 return (ret);
716 788 } /* oce_set_priv_prop */
717 789
718 790 /*
719 791 * function to get the value of a private property. Called from get_prop
720 792 *
721 793 * dev - software handle to the device
722 794 * name - string containing the property name
723 795 * size - length of the string contained name
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
724 796 * val - [OUT] pointer to the location where the result is returned
725 797 *
726 798 * return EINVAL => invalid request 0 => success
727 799 */
728 800 static int
729 801 oce_get_priv_prop(struct oce_dev *dev, const char *name,
730 802 uint_t size, void *val)
731 803 {
732 804 int value;
733 805
734 - if (strcmp(name, "_tx_ring_size") == 0) {
806 + if (strcmp(name, "_tx_rings") == 0) {
807 + value = dev->tx_rings;
808 + } else if (strcmp(name, "_tx_ring_size") == 0) {
735 809 value = dev->tx_ring_size;
736 810 } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
737 811 value = dev->tx_bcopy_limit;
812 + } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
813 + value = dev->tx_reclaim_threshold;
814 + } else if (strcmp(name, "_rx_rings") == 0) {
815 + value = dev->rx_rings;
816 + } else if (strcmp(name, "_rx_rings_per_group") == 0) {
817 + value = dev->rx_rings_per_group;
738 818 } else if (strcmp(name, "_rx_ring_size") == 0) {
739 819 value = dev->rx_ring_size;
740 820 } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
741 821 value = dev->rx_bcopy_limit;
822 + } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
823 + value = dev->rx_pkt_per_intr;
824 + } else if (strcmp(name, "_log_level") == 0) {
825 + value = (dev->mod_mask << 16UL) | dev->severity;
742 826 } else {
743 827 return (ENOTSUP);
744 828 }
745 829
746 830 (void) snprintf(val, size, "%d", value);
747 831 return (0);
748 832 } /* oce_get_priv_prop */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX