aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2009-03-02 03:07:32 -0500
committerDavid S. Miller <davem@davemloft.net>2009-03-03 01:45:24 -0500
commitbcc2cb3b97e37317c301309d7052bb61e6cce2c4 (patch)
treee1eed42ab44980713cc6b8d38e917e0d27ff9bcd /drivers
parentcdca8d02ea4229c2ccf3c27fb537b150843f67c9 (diff)
qlge: Add support for getting/setting port config.
This patch adds functionality to get and set port parameters. Currently it is used to set maximum TX/RX frame sizes. This process is also capable of setting: 1) Pause type: Standard or Priority based. 2) Loop back mode. 3) Enable Jumbo frame mode (included here...) Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/qlge/qlge.h6
-rw-r--r--drivers/net/qlge/qlge_main.c14
-rw-r--r--drivers/net/qlge/qlge_mpi.c209
3 files changed, 228 insertions, 1 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 5f60ec4efb3c..6f9fd24bf384 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1450,6 +1450,7 @@ struct ql_adapter {
1450 1450
1451 u32 mailbox_in; 1451 u32 mailbox_in;
1452 u32 mailbox_out; 1452 u32 mailbox_out;
1453 struct mbox_params idc_mbc;
1453 struct mutex mpi_mutex; 1454 struct mutex mpi_mutex;
1454 1455
1455 int tx_ring_size; 1456 int tx_ring_size;
@@ -1486,6 +1487,8 @@ struct ql_adapter {
1486 u32 port_link_up; 1487 u32 port_link_up;
1487 u32 port_init; 1488 u32 port_init;
1488 u32 link_status; 1489 u32 link_status;
1490 u32 link_config;
1491 u32 max_frame_size;
1489 1492
1490 union flash_params flash; 1493 union flash_params flash;
1491 1494
@@ -1495,6 +1498,8 @@ struct ql_adapter {
1495 struct delayed_work asic_reset_work; 1498 struct delayed_work asic_reset_work;
1496 struct delayed_work mpi_reset_work; 1499 struct delayed_work mpi_reset_work;
1497 struct delayed_work mpi_work; 1500 struct delayed_work mpi_work;
1501 struct delayed_work mpi_port_cfg_work;
1502 struct completion ide_completion;
1498 struct nic_operations *nic_ops; 1503 struct nic_operations *nic_ops;
1499 u16 device_id; 1504 u16 device_id;
1500}; 1505};
@@ -1569,6 +1574,7 @@ void ql_queue_asic_error(struct ql_adapter *qdev);
1569u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); 1574u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
1570void ql_set_ethtool_ops(struct net_device *ndev); 1575void ql_set_ethtool_ops(struct net_device *ndev);
1571int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); 1576int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data);
1577void ql_mpi_port_cfg_work(struct work_struct *work);
1572int ql_mb_get_fw_state(struct ql_adapter *qdev); 1578int ql_mb_get_fw_state(struct ql_adapter *qdev);
1573 1579
1574#if 1 1580#if 1
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 29334d99b430..7c1ce5765759 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -837,7 +837,14 @@ exit:
837 837
838static int ql_8000_port_initialize(struct ql_adapter *qdev) 838static int ql_8000_port_initialize(struct ql_adapter *qdev)
839{ 839{
840 return ql_mb_get_fw_state(qdev); 840 int status;
841 status = ql_mb_get_fw_state(qdev);
842 if (status)
843 goto exit;
844 /* Wake up a worker to get/set the TX/RX frame sizes. */
845 queue_delayed_work(qdev->workqueue, &qdev->mpi_port_cfg_work, 0);
846exit:
847 return status;
841} 848}
842 849
843/* Take the MAC Core out of reset. 850/* Take the MAC Core out of reset.
@@ -3188,6 +3195,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
3188 cancel_delayed_work_sync(&qdev->asic_reset_work); 3195 cancel_delayed_work_sync(&qdev->asic_reset_work);
3189 cancel_delayed_work_sync(&qdev->mpi_reset_work); 3196 cancel_delayed_work_sync(&qdev->mpi_reset_work);
3190 cancel_delayed_work_sync(&qdev->mpi_work); 3197 cancel_delayed_work_sync(&qdev->mpi_work);
3198 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
3191 3199
3192 /* The default queue at index 0 is always processed in 3200 /* The default queue at index 0 is always processed in
3193 * a workqueue. 3201 * a workqueue.
@@ -3462,6 +3470,8 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu)
3462 3470
3463 if (ndev->mtu == 1500 && new_mtu == 9000) { 3471 if (ndev->mtu == 1500 && new_mtu == 9000) {
3464 QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n"); 3472 QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n");
3473 queue_delayed_work(qdev->workqueue,
3474 &qdev->mpi_port_cfg_work, 0);
3465 } else if (ndev->mtu == 9000 && new_mtu == 1500) { 3475 } else if (ndev->mtu == 9000 && new_mtu == 1500) {
3466 QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n"); 3476 QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n");
3467 } else if ((ndev->mtu == 1500 && new_mtu == 1500) || 3477 } else if ((ndev->mtu == 1500 && new_mtu == 1500) ||
@@ -3771,7 +3781,9 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
3771 INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); 3781 INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work);
3772 INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); 3782 INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work);
3773 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); 3783 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
3784 INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work);
3774 mutex_init(&qdev->mpi_mutex); 3785 mutex_init(&qdev->mpi_mutex);
3786 init_completion(&qdev->ide_completion);
3775 3787
3776 if (!cards_found) { 3788 if (!cards_found) {
3777 dev_info(&pdev->dev, "%s\n", DRV_STRING); 3789 dev_info(&pdev->dev, "%s\n", DRV_STRING);
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index 11102bec36b2..ef610c674dfb 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -138,6 +138,27 @@ end:
138 return status; 138 return status;
139} 139}
140 140
141/* Process an inter-device event completion.
142 * If good, signal the caller's completion.
143 */
144static int ql_idc_cmplt_aen(struct ql_adapter *qdev)
145{
146 int status;
147 struct mbox_params *mbcp = &qdev->idc_mbc;
148 mbcp->out_count = 4;
149 status = ql_get_mb_sts(qdev, mbcp);
150 if (status) {
151 QPRINTK(qdev, DRV, ERR,
152 "Could not read MPI, resetting RISC!\n");
153 ql_queue_fw_error(qdev);
154 } else
155 /* Wake up the sleeping mpi_idc_work thread that is
156 * waiting for this event.
157 */
158 complete(&qdev->ide_completion);
159
160 return status;
161}
141static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) 162static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
142{ 163{
143 mbcp->out_count = 2; 164 mbcp->out_count = 2;
@@ -241,6 +262,16 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
241 status = ql_get_mb_sts(qdev, mbcp); 262 status = ql_get_mb_sts(qdev, mbcp);
242 return status; 263 return status;
243 264
265 /* Process and inbound IDC event.
266 * This will happen when we're trying to
267 * change tx/rx max frame size, change pause
268 * paramters or loopback mode.
269 */
270 case AEN_IDC_CMPLT:
271 case AEN_IDC_EXT:
272 status = ql_idc_cmplt_aen(qdev);
273 break;
274
244 case AEN_LINK_UP: 275 case AEN_LINK_UP:
245 ql_link_up(qdev, mbcp); 276 ql_link_up(qdev, mbcp);
246 break; 277 break;
@@ -391,6 +422,182 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev)
391 return status; 422 return status;
392} 423}
393 424
425/* Get link settings and maximum frame size settings
426 * for the current port.
427 * Most likely will block.
428 */
429static int ql_mb_set_port_cfg(struct ql_adapter *qdev)
430{
431 struct mbox_params mbc;
432 struct mbox_params *mbcp = &mbc;
433 int status = 0;
434
435 memset(mbcp, 0, sizeof(struct mbox_params));
436
437 mbcp->in_count = 3;
438 mbcp->out_count = 1;
439
440 mbcp->mbox_in[0] = MB_CMD_SET_PORT_CFG;
441 mbcp->mbox_in[1] = qdev->link_config;
442 mbcp->mbox_in[2] = qdev->max_frame_size;
443
444
445 status = ql_mailbox_command(qdev, mbcp);
446 if (status)
447 return status;
448
449 if (mbcp->mbox_out[0] == MB_CMD_STS_INTRMDT) {
450 QPRINTK(qdev, DRV, ERR,
451 "Port Config sent, wait for IDC.\n");
452 } else if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
453 QPRINTK(qdev, DRV, ERR,
454 "Failed Set Port Configuration.\n");
455 status = -EIO;
456 }
457 return status;
458}
459
460/* Get link settings and maximum frame size settings
461 * for the current port.
462 * Most likely will block.
463 */
464static int ql_mb_get_port_cfg(struct ql_adapter *qdev)
465{
466 struct mbox_params mbc;
467 struct mbox_params *mbcp = &mbc;
468 int status = 0;
469
470 memset(mbcp, 0, sizeof(struct mbox_params));
471
472 mbcp->in_count = 1;
473 mbcp->out_count = 3;
474
475 mbcp->mbox_in[0] = MB_CMD_GET_PORT_CFG;
476
477 status = ql_mailbox_command(qdev, mbcp);
478 if (status)
479 return status;
480
481 if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
482 QPRINTK(qdev, DRV, ERR,
483 "Failed Get Port Configuration.\n");
484 status = -EIO;
485 } else {
486 QPRINTK(qdev, DRV, DEBUG,
487 "Passed Get Port Configuration.\n");
488 qdev->link_config = mbcp->mbox_out[1];
489 qdev->max_frame_size = mbcp->mbox_out[2];
490 }
491 return status;
492}
493
494/* IDC - Inter Device Communication...
495 * Some firmware commands require consent of adjacent FCOE
496 * function. This function waits for the OK, or a
497 * counter-request for a little more time.i
498 * The firmware will complete the request if the other
499 * function doesn't respond.
500 */
501static int ql_idc_wait(struct ql_adapter *qdev)
502{
503 int status = -ETIMEDOUT;
504 long wait_time = 1 * HZ;
505 struct mbox_params *mbcp = &qdev->idc_mbc;
506 do {
507 /* Wait here for the command to complete
508 * via the IDC process.
509 */
510 wait_time =
511 wait_for_completion_timeout(&qdev->ide_completion,
512 wait_time);
513 if (!wait_time) {
514 QPRINTK(qdev, DRV, ERR,
515 "IDC Timeout.\n");
516 break;
517 }
518 /* Now examine the response from the IDC process.
519 * We might have a good completion or a request for
520 * more wait time.
521 */
522 if (mbcp->mbox_out[0] == AEN_IDC_EXT) {
523 QPRINTK(qdev, DRV, ERR,
524 "IDC Time Extension from function.\n");
525 wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f;
526 } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) {
527 QPRINTK(qdev, DRV, ERR,
528 "IDC Success.\n");
529 status = 0;
530 break;
531 } else {
532 QPRINTK(qdev, DRV, ERR,
533 "IDC: Invalid State 0x%.04x.\n",
534 mbcp->mbox_out[0]);
535 status = -EIO;
536 break;
537 }
538 } while (wait_time);
539
540 return status;
541}
542
543/* API called in work thread context to set new TX/RX
544 * maximum frame size values to match MTU.
545 */
546static int ql_set_port_cfg(struct ql_adapter *qdev)
547{
548 int status;
549 status = ql_mb_set_port_cfg(qdev);
550 if (status)
551 return status;
552 status = ql_idc_wait(qdev);
553 return status;
554}
555
556/* The following routines are worker threads that process
557 * events that may sleep waiting for completion.
558 */
559
560/* This thread gets the maximum TX and RX frame size values
561 * from the firmware and, if necessary, changes them to match
562 * the MTU setting.
563 */
564void ql_mpi_port_cfg_work(struct work_struct *work)
565{
566 struct ql_adapter *qdev =
567 container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
568 struct net_device *ndev = qdev->ndev;
569 int status;
570
571 status = ql_mb_get_port_cfg(qdev);
572 if (status) {
573 QPRINTK(qdev, DRV, ERR,
574 "Bug: Failed to get port config data.\n");
575 goto err;
576 }
577
578 if (ndev->mtu <= 2500)
579 goto end;
580 else if (qdev->link_config & CFG_JUMBO_FRAME_SIZE &&
581 qdev->max_frame_size ==
582 CFG_DEFAULT_MAX_FRAME_SIZE)
583 goto end;
584
585 qdev->link_config |= CFG_JUMBO_FRAME_SIZE;
586 qdev->max_frame_size = CFG_DEFAULT_MAX_FRAME_SIZE;
587 status = ql_set_port_cfg(qdev);
588 if (status) {
589 QPRINTK(qdev, DRV, ERR,
590 "Bug: Failed to set port config data.\n");
591 goto err;
592 }
593end:
594 clear_bit(QL_PORT_CFG, &qdev->flags);
595 return;
596err:
597 ql_queue_fw_error(qdev);
598 goto end;
599}
600
394void ql_mpi_work(struct work_struct *work) 601void ql_mpi_work(struct work_struct *work)
395{ 602{
396 struct ql_adapter *qdev = 603 struct ql_adapter *qdev =
@@ -414,5 +621,7 @@ void ql_mpi_reset_work(struct work_struct *work)
414{ 621{
415 struct ql_adapter *qdev = 622 struct ql_adapter *qdev =
416 container_of(work, struct ql_adapter, mpi_reset_work.work); 623 container_of(work, struct ql_adapter, mpi_reset_work.work);
624 cancel_delayed_work_sync(&qdev->mpi_work);
625 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
417 ql_soft_reset_mpi_risc(qdev); 626 ql_soft_reset_mpi_risc(qdev);
418} 627}