|
@@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
40
|
40
|
#include <ipxe/ethernet.h>
|
41
|
41
|
#include <ipxe/fcoe.h>
|
42
|
42
|
#include <ipxe/vlan.h>
|
|
43
|
+#include <ipxe/bofm.h>
|
43
|
44
|
#include "hermon.h"
|
44
|
45
|
|
45
|
46
|
/**
|
|
@@ -496,6 +497,17 @@ hermon_cmd_mgid_hash ( struct hermon *hermon, const union ib_gid *gid,
|
496
|
497
|
0, gid, 0, hash );
|
497
|
498
|
}
|
498
|
499
|
|
|
500
|
+static inline int
|
|
501
|
+hermon_cmd_mod_stat_cfg ( struct hermon *hermon, unsigned int mode,
|
|
502
|
+ unsigned int input_mod,
|
|
503
|
+ struct hermonprm_scalar_parameter *portion ) {
|
|
504
|
+ return hermon_cmd ( hermon,
|
|
505
|
+ HERMON_HCR_INOUT_CMD ( HERMON_HCR_MOD_STAT_CFG,
|
|
506
|
+ 0, sizeof ( *portion ),
|
|
507
|
+ 0, sizeof ( *portion ) ),
|
|
508
|
+ mode, portion, input_mod, portion );
|
|
509
|
+}
|
|
510
|
+
|
499
|
511
|
static inline int
|
500
|
512
|
hermon_cmd_query_port ( struct hermon *hermon, unsigned int port,
|
501
|
513
|
struct hermonprm_query_port_cap *query_port ) {
|
|
@@ -682,6 +694,59 @@ static void hermon_free_mtt ( struct hermon *hermon,
|
682
|
694
|
mtt->num_pages );
|
683
|
695
|
}
|
684
|
696
|
|
|
697
|
+/***************************************************************************
|
|
698
|
+ *
|
|
699
|
+ * Static configuration operations
|
|
700
|
+ *
|
|
701
|
+ ***************************************************************************
|
|
702
|
+ */
|
|
703
|
+
|
|
704
|
+/**
|
|
705
|
+ * Calculate offset within static configuration
|
|
706
|
+ *
|
|
707
|
+ * @v field Field
|
|
708
|
+ * @ret offset Offset
|
|
709
|
+ */
|
|
710
|
+#define HERMON_MOD_STAT_CFG_OFFSET( field ) \
|
|
711
|
+ ( ( MLX_BIT_OFFSET ( struct hermonprm_mod_stat_cfg_st, field ) / 8 ) \
|
|
712
|
+ & ~( sizeof ( struct hermonprm_scalar_parameter ) - 1 ) )
|
|
713
|
+
|
|
714
|
+/**
|
|
715
|
+ * Query or modify static configuration
|
|
716
|
+ *
|
|
717
|
+ * @v hermon Hermon device
|
|
718
|
+ * @v port Port
|
|
719
|
+ * @v mode Command mode
|
|
720
|
+ * @v offset Offset within static configuration
|
|
721
|
+ * @v stat_cfg Static configuration
|
|
722
|
+ * @ret rc Return status code
|
|
723
|
+ */
|
|
724
|
+static int hermon_mod_stat_cfg ( struct hermon *hermon, unsigned int port,
|
|
725
|
+ unsigned int mode, unsigned int offset,
|
|
726
|
+ struct hermonprm_mod_stat_cfg *stat_cfg ) {
|
|
727
|
+ struct hermonprm_scalar_parameter *portion =
|
|
728
|
+ ( ( void * ) &stat_cfg->u.bytes[offset] );
|
|
729
|
+ struct hermonprm_mod_stat_cfg_input_mod mod;
|
|
730
|
+ int rc;
|
|
731
|
+
|
|
732
|
+ /* Sanity check */
|
|
733
|
+ assert ( ( offset % sizeof ( *portion ) ) == 0 );
|
|
734
|
+
|
|
735
|
+ /* Construct input modifier */
|
|
736
|
+ memset ( &mod, 0, sizeof ( mod ) );
|
|
737
|
+ MLX_FILL_2 ( &mod, 0,
|
|
738
|
+ portnum, port,
|
|
739
|
+ offset, offset );
|
|
740
|
+
|
|
741
|
+ /* Issue command */
|
|
742
|
+ if ( ( rc = hermon_cmd_mod_stat_cfg ( hermon, mode,
|
|
743
|
+ be32_to_cpu ( mod.u.dwords[0] ),
|
|
744
|
+ portion ) ) != 0 )
|
|
745
|
+ return rc;
|
|
746
|
+
|
|
747
|
+ return 0;
|
|
748
|
+}
|
|
749
|
+
|
685
|
750
|
/***************************************************************************
|
686
|
751
|
*
|
687
|
752
|
* MAD operations
|
|
@@ -3230,6 +3295,103 @@ static void hermon_free_icm ( struct hermon *hermon ) {
|
3230
|
3295
|
hermon->icm = UNULL;
|
3231
|
3296
|
}
|
3232
|
3297
|
|
|
3298
|
+/***************************************************************************
|
|
3299
|
+ *
|
|
3300
|
+ * BOFM interface
|
|
3301
|
+ *
|
|
3302
|
+ ***************************************************************************
|
|
3303
|
+ */
|
|
3304
|
+
|
|
3305
|
+/**
|
|
3306
|
+ * Harvest Ethernet MAC for BOFM
|
|
3307
|
+ *
|
|
3308
|
+ * @v bofm BOFM device
|
|
3309
|
+ * @v mport Multi-port index
|
|
3310
|
+ * @v mac MAC to fill in
|
|
3311
|
+ * @ret rc Return status code
|
|
3312
|
+ */
|
|
3313
|
+static int hermon_bofm_harvest ( struct bofm_device *bofm, unsigned int mport,
|
|
3314
|
+ uint8_t *mac ) {
|
|
3315
|
+ struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
|
|
3316
|
+ struct hermonprm_mod_stat_cfg stat_cfg;
|
|
3317
|
+ union {
|
|
3318
|
+ uint8_t bytes[8];
|
|
3319
|
+ uint32_t dwords[2];
|
|
3320
|
+ } buf;
|
|
3321
|
+ int rc;
|
|
3322
|
+
|
|
3323
|
+ /* Query static configuration */
|
|
3324
|
+ if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
|
|
3325
|
+ HERMON_MOD_STAT_CFG_QUERY,
|
|
3326
|
+ HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
|
|
3327
|
+ &stat_cfg ) ) != 0 ) {
|
|
3328
|
+ DBGC ( hermon, "Hermon %p port %d could not query "
|
|
3329
|
+ "configuration: %s\n", hermon, mport, strerror ( rc ) );
|
|
3330
|
+ return rc;
|
|
3331
|
+ }
|
|
3332
|
+
|
|
3333
|
+ /* Retrieve MAC address */
|
|
3334
|
+ buf.dwords[0] = htonl ( MLX_GET ( &stat_cfg, mac_high ) );
|
|
3335
|
+ buf.dwords[1] = htonl ( MLX_GET ( &stat_cfg, mac_low ) );
|
|
3336
|
+ memcpy ( mac, &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ],
|
|
3337
|
+ ETH_ALEN );
|
|
3338
|
+
|
|
3339
|
+ DBGC ( hermon, "Hermon %p port %d harvested MAC address %s\n",
|
|
3340
|
+ hermon, mport, eth_ntoa ( mac ) );
|
|
3341
|
+
|
|
3342
|
+ return 0;
|
|
3343
|
+}
|
|
3344
|
+
|
|
3345
|
+/**
|
|
3346
|
+ * Update Ethernet MAC for BOFM
|
|
3347
|
+ *
|
|
3348
|
+ * @v bofm BOFM device
|
|
3349
|
+ * @v mport Multi-port index
|
|
3350
|
+ * @v mac MAC to fill in
|
|
3351
|
+ * @ret rc Return status code
|
|
3352
|
+ */
|
|
3353
|
+static int hermon_bofm_update ( struct bofm_device *bofm, unsigned int mport,
|
|
3354
|
+ const uint8_t *mac ) {
|
|
3355
|
+ struct hermon *hermon = container_of ( bofm, struct hermon, bofm );
|
|
3356
|
+ struct hermonprm_mod_stat_cfg stat_cfg;
|
|
3357
|
+ union {
|
|
3358
|
+ uint8_t bytes[8];
|
|
3359
|
+ uint32_t dwords[2];
|
|
3360
|
+ } buf;
|
|
3361
|
+ int rc;
|
|
3362
|
+
|
|
3363
|
+ /* Prepare MAC address */
|
|
3364
|
+ memset ( &buf, 0, sizeof ( buf ) );
|
|
3365
|
+ memcpy ( &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ], mac,
|
|
3366
|
+ ETH_ALEN );
|
|
3367
|
+
|
|
3368
|
+ /* Modify static configuration */
|
|
3369
|
+ memset ( &stat_cfg, 0, sizeof ( stat_cfg ) );
|
|
3370
|
+ MLX_FILL_2 ( &stat_cfg, 36,
|
|
3371
|
+ mac_m, 1,
|
|
3372
|
+ mac_high, ntohl ( buf.dwords[0] ) );
|
|
3373
|
+ MLX_FILL_1 ( &stat_cfg, 37, mac_low, ntohl ( buf.dwords[1] ) );
|
|
3374
|
+ if ( ( rc = hermon_mod_stat_cfg ( hermon, mport,
|
|
3375
|
+ HERMON_MOD_STAT_CFG_SET,
|
|
3376
|
+ HERMON_MOD_STAT_CFG_OFFSET ( mac_m ),
|
|
3377
|
+ &stat_cfg ) ) != 0 ) {
|
|
3378
|
+ DBGC ( hermon, "Hermon %p port %d could not modify "
|
|
3379
|
+ "configuration: %s\n", hermon, mport, strerror ( rc ) );
|
|
3380
|
+ return rc;
|
|
3381
|
+ }
|
|
3382
|
+
|
|
3383
|
+ DBGC ( hermon, "Hermon %p port %d updated MAC address to %s\n",
|
|
3384
|
+ hermon, mport, eth_ntoa ( mac ) );
|
|
3385
|
+
|
|
3386
|
+ return 0;
|
|
3387
|
+}
|
|
3388
|
+
|
|
3389
|
+/** Hermon BOFM operations */
|
|
3390
|
+static struct bofm_operations hermon_bofm_operations = {
|
|
3391
|
+ .harvest = hermon_bofm_harvest,
|
|
3392
|
+ .update = hermon_bofm_update,
|
|
3393
|
+};
|
|
3394
|
+
|
3233
|
3395
|
/***************************************************************************
|
3234
|
3396
|
*
|
3235
|
3397
|
* PCI interface
|
|
@@ -3325,6 +3487,72 @@ static void hermon_reset ( struct hermon *hermon,
|
3325
|
3487
|
pci_restore ( pci, &backup, backup_exclude );
|
3326
|
3488
|
}
|
3327
|
3489
|
|
|
3490
|
+/**
|
|
3491
|
+ * Allocate Hermon device
|
|
3492
|
+ *
|
|
3493
|
+ * @v pci PCI device
|
|
3494
|
+ * @v id PCI ID
|
|
3495
|
+ * @ret rc Return status code
|
|
3496
|
+ */
|
|
3497
|
+static struct hermon * hermon_alloc ( void ) {
|
|
3498
|
+ struct hermon *hermon;
|
|
3499
|
+
|
|
3500
|
+ /* Allocate Hermon device */
|
|
3501
|
+ hermon = zalloc ( sizeof ( *hermon ) );
|
|
3502
|
+ if ( ! hermon )
|
|
3503
|
+ goto err_hermon;
|
|
3504
|
+
|
|
3505
|
+ /* Allocate space for mailboxes */
|
|
3506
|
+ hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
|
|
3507
|
+ HERMON_MBOX_ALIGN );
|
|
3508
|
+ if ( ! hermon->mailbox_in )
|
|
3509
|
+ goto err_mailbox_in;
|
|
3510
|
+ hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
|
|
3511
|
+ HERMON_MBOX_ALIGN );
|
|
3512
|
+ if ( ! hermon->mailbox_out )
|
|
3513
|
+ goto err_mailbox_out;
|
|
3514
|
+
|
|
3515
|
+ return hermon;
|
|
3516
|
+
|
|
3517
|
+ free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
|
|
3518
|
+ err_mailbox_out:
|
|
3519
|
+ free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
|
|
3520
|
+ err_mailbox_in:
|
|
3521
|
+ free ( hermon );
|
|
3522
|
+ err_hermon:
|
|
3523
|
+ return NULL;
|
|
3524
|
+}
|
|
3525
|
+
|
|
3526
|
+/**
|
|
3527
|
+ * Free Hermon device
|
|
3528
|
+ *
|
|
3529
|
+ * @v hermon Hermon device
|
|
3530
|
+ */
|
|
3531
|
+static void hermon_free ( struct hermon *hermon ) {
|
|
3532
|
+
|
|
3533
|
+ free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
|
|
3534
|
+ free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
|
|
3535
|
+ free ( hermon );
|
|
3536
|
+}
|
|
3537
|
+
|
|
3538
|
+/**
|
|
3539
|
+ * Initialise Hermon PCI parameters
|
|
3540
|
+ *
|
|
3541
|
+ * @v hermon Hermon device
|
|
3542
|
+ * @v pci PCI device
|
|
3543
|
+ */
|
|
3544
|
+static void hermon_pci_init ( struct hermon *hermon, struct pci_device *pci ) {
|
|
3545
|
+
|
|
3546
|
+ /* Fix up PCI device */
|
|
3547
|
+ adjust_pci_device ( pci );
|
|
3548
|
+
|
|
3549
|
+ /* Get PCI BARs */
|
|
3550
|
+ hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR),
|
|
3551
|
+ HERMON_PCI_CONFIG_BAR_SIZE );
|
|
3552
|
+ hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
|
|
3553
|
+ HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
|
|
3554
|
+}
|
|
3555
|
+
|
3328
|
3556
|
/**
|
3329
|
3557
|
* Probe PCI device
|
3330
|
3558
|
*
|
|
@@ -3342,39 +3570,19 @@ static int hermon_probe ( struct pci_device *pci ) {
|
3342
|
3570
|
int rc;
|
3343
|
3571
|
|
3344
|
3572
|
/* Allocate Hermon device */
|
3345
|
|
- hermon = zalloc ( sizeof ( *hermon ) );
|
|
3573
|
+ hermon = hermon_alloc();
|
3346
|
3574
|
if ( ! hermon ) {
|
3347
|
3575
|
rc = -ENOMEM;
|
3348
|
|
- goto err_alloc_hermon;
|
|
3576
|
+ goto err_alloc;
|
3349
|
3577
|
}
|
3350
|
3578
|
pci_set_drvdata ( pci, hermon );
|
3351
|
3579
|
|
3352
|
|
- /* Fix up PCI device */
|
3353
|
|
- adjust_pci_device ( pci );
|
3354
|
|
-
|
3355
|
|
- /* Get PCI BARs */
|
3356
|
|
- hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR),
|
3357
|
|
- HERMON_PCI_CONFIG_BAR_SIZE );
|
3358
|
|
- hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ),
|
3359
|
|
- HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
|
|
3580
|
+ /* Initialise PCI parameters */
|
|
3581
|
+ hermon_pci_init ( hermon, pci );
|
3360
|
3582
|
|
3361
|
3583
|
/* Reset device */
|
3362
|
3584
|
hermon_reset ( hermon, pci );
|
3363
|
3585
|
|
3364
|
|
- /* Allocate space for mailboxes */
|
3365
|
|
- hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE,
|
3366
|
|
- HERMON_MBOX_ALIGN );
|
3367
|
|
- if ( ! hermon->mailbox_in ) {
|
3368
|
|
- rc = -ENOMEM;
|
3369
|
|
- goto err_mailbox_in;
|
3370
|
|
- }
|
3371
|
|
- hermon->mailbox_out = malloc_dma ( HERMON_MBOX_SIZE,
|
3372
|
|
- HERMON_MBOX_ALIGN );
|
3373
|
|
- if ( ! hermon->mailbox_out ) {
|
3374
|
|
- rc = -ENOMEM;
|
3375
|
|
- goto err_mailbox_out;
|
3376
|
|
- }
|
3377
|
|
-
|
3378
|
3586
|
/* Start firmware */
|
3379
|
3587
|
if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
|
3380
|
3588
|
goto err_start_firmware;
|
|
@@ -3483,12 +3691,8 @@ static int hermon_probe ( struct pci_device *pci ) {
|
3483
|
3691
|
err_get_cap:
|
3484
|
3692
|
hermon_stop_firmware ( hermon );
|
3485
|
3693
|
err_start_firmware:
|
3486
|
|
- free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
|
3487
|
|
- err_mailbox_out:
|
3488
|
|
- free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
|
3489
|
|
- err_mailbox_in:
|
3490
|
|
- free ( hermon );
|
3491
|
|
- err_alloc_hermon:
|
|
3694
|
+ hermon_free ( hermon );
|
|
3695
|
+ err_alloc:
|
3492
|
3696
|
return rc;
|
3493
|
3697
|
}
|
3494
|
3698
|
|
|
@@ -3511,15 +3715,65 @@ static void hermon_remove ( struct pci_device *pci ) {
|
3511
|
3715
|
hermon_free_icm ( hermon );
|
3512
|
3716
|
hermon_stop_firmware ( hermon );
|
3513
|
3717
|
hermon_stop_firmware ( hermon );
|
3514
|
|
- free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
|
3515
|
|
- free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
|
3516
|
3718
|
for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
|
3517
|
3719
|
netdev_nullify ( hermon->port[i].netdev );
|
3518
|
3720
|
netdev_put ( hermon->port[i].netdev );
|
3519
|
3721
|
}
|
3520
|
3722
|
for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
|
3521
|
3723
|
ibdev_put ( hermon->port[i].ibdev );
|
3522
|
|
- free ( hermon );
|
|
3724
|
+ hermon_free ( hermon );
|
|
3725
|
+}
|
|
3726
|
+
|
|
3727
|
+/**
|
|
3728
|
+ * Probe PCI device for BOFM
|
|
3729
|
+ *
|
|
3730
|
+ * @v pci PCI device
|
|
3731
|
+ * @v id PCI ID
|
|
3732
|
+ * @ret rc Return status code
|
|
3733
|
+ */
|
|
3734
|
+static int hermon_bofm_probe ( struct pci_device *pci ) {
|
|
3735
|
+ struct hermon *hermon;
|
|
3736
|
+ int rc;
|
|
3737
|
+
|
|
3738
|
+ /* Allocate Hermon device */
|
|
3739
|
+ hermon = hermon_alloc();
|
|
3740
|
+ if ( ! hermon ) {
|
|
3741
|
+ rc = -ENOMEM;
|
|
3742
|
+ goto err_alloc;
|
|
3743
|
+ }
|
|
3744
|
+ pci_set_drvdata ( pci, hermon );
|
|
3745
|
+
|
|
3746
|
+ /* Initialise PCI parameters */
|
|
3747
|
+ hermon_pci_init ( hermon, pci );
|
|
3748
|
+
|
|
3749
|
+ /* Initialise BOFM device */
|
|
3750
|
+ bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );
|
|
3751
|
+
|
|
3752
|
+ /* Register BOFM device */
|
|
3753
|
+ if ( ( rc = bofm_register ( &hermon->bofm ) ) != 0 ) {
|
|
3754
|
+ DBGC ( hermon, "Hermon %p could not register BOFM device: "
|
|
3755
|
+ "%s\n", hermon, strerror ( rc ) );
|
|
3756
|
+ goto err_bofm_register;
|
|
3757
|
+ }
|
|
3758
|
+
|
|
3759
|
+ return 0;
|
|
3760
|
+
|
|
3761
|
+ err_bofm_register:
|
|
3762
|
+ hermon_free ( hermon );
|
|
3763
|
+ err_alloc:
|
|
3764
|
+ return rc;
|
|
3765
|
+}
|
|
3766
|
+
|
|
3767
|
+/**
|
|
3768
|
+ * Remove PCI device for BOFM
|
|
3769
|
+ *
|
|
3770
|
+ * @v pci PCI device
|
|
3771
|
+ */
|
|
3772
|
+static void hermon_bofm_remove ( struct pci_device *pci ) {
|
|
3773
|
+ struct hermon *hermon = pci_get_drvdata ( pci );
|
|
3774
|
+
|
|
3775
|
+ bofm_unregister ( &hermon->bofm );
|
|
3776
|
+ hermon_free ( hermon );
|
3523
|
3777
|
}
|
3524
|
3778
|
|
3525
|
3779
|
static struct pci_device_id hermon_nics[] = {
|
|
@@ -3543,3 +3797,10 @@ struct pci_driver hermon_driver __pci_driver = {
|
3543
|
3797
|
.probe = hermon_probe,
|
3544
|
3798
|
.remove = hermon_remove,
|
3545
|
3799
|
};
|
|
3800
|
+
|
|
3801
|
+struct pci_driver hermon_bofm_driver __bofm_driver = {
|
|
3802
|
+ .ids = hermon_nics,
|
|
3803
|
+ .id_count = ( sizeof ( hermon_nics ) / sizeof ( hermon_nics[0] ) ),
|
|
3804
|
+ .probe = hermon_bofm_probe,
|
|
3805
|
+ .remove = hermon_bofm_remove,
|
|
3806
|
+};
|