Print this page
6064 ixgbe needs X550 support

@@ -295,17 +295,28 @@
         int err = 0;
         uint32_t flow_control;
         uint32_t cur_mtu, new_mtu;
         uint32_t rx_size;
         uint32_t tx_size;
+        ixgbe_link_speed speeds = 0;
 
         mutex_enter(&ixgbe->gen_lock);
         if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
                 mutex_exit(&ixgbe->gen_lock);
                 return (ECANCELED);
         }
 
+        /*
+         * We cannot always rely on the common code maintaining
+         * hw->phy.speeds_supported, therefore we fall back to use the recorded
+         * supported speeds which were obtained during instance init in
+         * ixgbe_init_params().
+         */
+        speeds = hw->phy.speeds_supported;
+        if (speeds == 0)
+                speeds = ixgbe->speeds_supported;
+
         if (ixgbe->loopback_mode != IXGBE_LB_NONE &&
             ixgbe_param_locked(pr_num)) {
                 /*
                  * All en_* parameters are locked (read-only)
                  * while the device is in any sort of loopback mode.

@@ -312,43 +323,61 @@
                  */
                 mutex_exit(&ixgbe->gen_lock);
                 return (EBUSY);
         }
 
+        /*
+         * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
+         * read-only on non-baseT PHYs.
+         */
         switch (pr_num) {
         case MAC_PROP_EN_10GFDX_CAP:
-                /* read/write on copper, read-only on serdes */
-                if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
-                        err = ENOTSUP;
-                        break;
-                } else {
+                if (hw->phy.media_type == ixgbe_media_type_copper &&
+                    speeds & IXGBE_LINK_SPEED_10GB_FULL) {
                         ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val;
-                        ixgbe->param_adv_10000fdx_cap = *(uint8_t *)pr_val;
                         goto setup_link;
+                } else {
+                        err = ENOTSUP;
+                        break;
                 }
-        case MAC_PROP_EN_1000FDX_CAP:
-                /* read/write on copper, read-only on serdes */
-                if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
+        case MAC_PROP_EN_5000FDX_CAP:
+                if (hw->phy.media_type == ixgbe_media_type_copper &&
+                    speeds & IXGBE_LINK_SPEED_5GB_FULL) {
+                        ixgbe->param_en_5000fdx_cap = *(uint8_t *)pr_val;
+                        goto setup_link;
+                } else {
                         err = ENOTSUP;
                         break;
+                }
+        case MAC_PROP_EN_2500FDX_CAP:
+                if (hw->phy.media_type == ixgbe_media_type_copper &&
+                    speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
+                        ixgbe->param_en_2500fdx_cap = *(uint8_t *)pr_val;
+                        goto setup_link;
                 } else {
+                        err = ENOTSUP;
+                        break;
+                }
+        case MAC_PROP_EN_1000FDX_CAP:
+                if (hw->phy.media_type == ixgbe_media_type_copper &&
+                    speeds & IXGBE_LINK_SPEED_1GB_FULL) {
                         ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val;
-                        ixgbe->param_adv_1000fdx_cap = *(uint8_t *)pr_val;
                         goto setup_link;
-                }
-        case MAC_PROP_EN_100FDX_CAP:
-                /* read/write on copper, read-only on serdes */
-                if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
+                } else {
                         err = ENOTSUP;
                         break;
-                } else {
+                }
+        case MAC_PROP_EN_100FDX_CAP:
+                if (hw->phy.media_type == ixgbe_media_type_copper &&
+                    speeds & IXGBE_LINK_SPEED_100_FULL) {
                         ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val;
-                        ixgbe->param_adv_100fdx_cap = *(uint8_t *)pr_val;
                         goto setup_link;
+                } else {
+                        err = ENOTSUP;
+                        break;
                 }
         case MAC_PROP_AUTONEG:
-                /* read/write on copper, read-only on serdes */
                 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
                         err = ENOTSUP;
                         break;
                 } else {
                         ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val;

@@ -380,10 +409,12 @@
                             IXGBE_SUCCESS)
                                 err = EINVAL;
                 }
                 break;
         case MAC_PROP_ADV_10GFDX_CAP:
+        case MAC_PROP_ADV_5000FDX_CAP:
+        case MAC_PROP_ADV_2500FDX_CAP:
         case MAC_PROP_ADV_1000FDX_CAP:
         case MAC_PROP_ADV_100FDX_CAP:
         case MAC_PROP_STATUS:
         case MAC_PROP_SPEED:
         case MAC_PROP_DUPLEX:

@@ -446,11 +477,22 @@
         ixgbe_t *ixgbe = (ixgbe_t *)arg;
         struct ixgbe_hw *hw = &ixgbe->hw;
         int err = 0;
         uint32_t flow_control;
         uint64_t tmp = 0;
+        ixgbe_link_speed speeds = 0;
 
+        /*
+         * We cannot always rely on the common code maintaining
+         * hw->phy.speeds_supported, therefore we fall back to use the recorded
+         * supported speeds which were obtained during instance init in
+         * ixgbe_init_params().
+         */
+        speeds = hw->phy.speeds_supported;
+        if (speeds == 0)
+                speeds = ixgbe->speeds_supported;
+
         switch (pr_num) {
         case MAC_PROP_DUPLEX:
                 ASSERT(pr_valsize >= sizeof (link_duplex_t));
                 bcopy(&ixgbe->link_duplex, pr_val,
                     sizeof (link_duplex_t));

@@ -481,26 +523,68 @@
                                 break;
                 }
                 bcopy(&flow_control, pr_val, sizeof (flow_control));
                 break;
         case MAC_PROP_ADV_10GFDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
         case MAC_PROP_EN_10GFDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
+        case MAC_PROP_ADV_5000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
+                        *(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
+                else
+                        err = ENOTSUP;
+                break;
+        case MAC_PROP_EN_5000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
+                        *(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
+                else
+                        err = ENOTSUP;
+                break;
+        case MAC_PROP_ADV_2500FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
+                        *(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
+                else
+                        err = ENOTSUP;
+                break;
+        case MAC_PROP_EN_2500FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
+                        *(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
+                else
+                        err = ENOTSUP;
+                break;
         case MAC_PROP_ADV_1000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
         case MAC_PROP_EN_1000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
         case MAC_PROP_ADV_100FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_100_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
         case MAC_PROP_EN_100FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_100_FULL)
                 *(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
+                else
+                        err = ENOTSUP;
                 break;
         case MAC_PROP_PRIVATE:
                 err = ixgbe_get_priv_prop(ixgbe, pr_name,
                     pr_valsize, pr_val);
                 break;

@@ -514,33 +598,115 @@
 void
 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
     mac_prop_info_handle_t prh)
 {
         ixgbe_t *ixgbe = (ixgbe_t *)arg;
+        struct ixgbe_hw *hw = &ixgbe->hw;
         uint_t perm;
+        uint8_t value;
+        ixgbe_link_speed speeds = 0;
 
+        /*
+         * We cannot always rely on the common code maintaining
+         * hw->phy.speeds_supported, therefore we fall back to use the
+         * recorded supported speeds which were obtained during instance init in
+         * ixgbe_init_params().
+         */
+        speeds = hw->phy.speeds_supported;
+        if (speeds == 0)
+                speeds = ixgbe->speeds_supported;
+
         switch (pr_num) {
         case MAC_PROP_DUPLEX:
         case MAC_PROP_SPEED:
                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
                 break;
 
         case MAC_PROP_ADV_100FDX_CAP:
+                mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
+                value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
+                mac_prop_info_set_default_uint8(prh, value);
+                break;
+
         case MAC_PROP_ADV_1000FDX_CAP:
+                mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
+                value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
+                mac_prop_info_set_default_uint8(prh, value);
+                break;
+
+        case MAC_PROP_ADV_2500FDX_CAP:
+                mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
+                value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
+                mac_prop_info_set_default_uint8(prh, value);
+                break;
+
+        case MAC_PROP_ADV_5000FDX_CAP:
+                mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
+                value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
+                mac_prop_info_set_default_uint8(prh, value);
+                break;
+
         case MAC_PROP_ADV_10GFDX_CAP:
                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
-                mac_prop_info_set_default_uint8(prh, 1);
+                value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
+                mac_prop_info_set_default_uint8(prh, value);
                 break;
 
+        /*
+         * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
+         * read-only on non-baseT (SFP) PHYs.
+         */
         case MAC_PROP_AUTONEG:
+                perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
+                    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
+                mac_prop_info_set_perm(prh, perm);
+                mac_prop_info_set_default_uint8(prh, 1);
+                break;
+
         case MAC_PROP_EN_10GFDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
+                        perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
+                            MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
+                        mac_prop_info_set_perm(prh, perm);
+                        mac_prop_info_set_default_uint8(prh, 1);
+                }
+                break;
+
+        case MAC_PROP_EN_5000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
+                        perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
+                            MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
+                        mac_prop_info_set_perm(prh, perm);
+                        mac_prop_info_set_default_uint8(prh, 1);
+                }
+                break;
+
+        case MAC_PROP_EN_2500FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
+                        perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
+                            MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
+                        mac_prop_info_set_perm(prh, perm);
+                        mac_prop_info_set_default_uint8(prh, 1);
+                }
+                break;
+
         case MAC_PROP_EN_1000FDX_CAP:
+                if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
+                        perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
+                            MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
+                        mac_prop_info_set_perm(prh, perm);
+                        mac_prop_info_set_default_uint8(prh, 1);
+                }
+                break;
+
         case MAC_PROP_EN_100FDX_CAP:
-                perm = (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) ?
+                if (speeds & IXGBE_LINK_SPEED_100_FULL) {
+                        perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
                     MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
                 mac_prop_info_set_perm(prh, perm);
                 mac_prop_info_set_default_uint8(prh, 1);
+                }
                 break;
 
         case MAC_PROP_FLOWCTRL:
                 mac_prop_info_set_default_link_flowctrl(prh,
                     LINK_FLOWCTRL_NONE);

@@ -593,10 +759,12 @@
          * All en_* parameters are locked (read-only) while
          * the device is in any sort of loopback mode ...
          */
         switch (pr_num) {
                 case MAC_PROP_EN_10GFDX_CAP:
+                case MAC_PROP_EN_5000FDX_CAP:
+                case MAC_PROP_EN_2500FDX_CAP:
                 case MAC_PROP_EN_1000FDX_CAP:
                 case MAC_PROP_EN_100FDX_CAP:
                 case MAC_PROP_AUTONEG:
                 case MAC_PROP_FLOWCTRL:
                         return (B_TRUE);

@@ -710,16 +878,18 @@
                         err = EINVAL;
                 else {
                         ixgbe->intr_throttling[0] = (uint32_t)result;
 
                         /*
-                         * 82599 and X540 require the interrupt throttling
+                         * 82599, X540 and X550 require the interrupt throttling
                          * rate is a multiple of 8. This is enforced by the
                          * register definiton.
                          */
                         if (hw->mac.type == ixgbe_mac_82599EB ||
-                            hw->mac.type == ixgbe_mac_X540) {
+                            hw->mac.type == ixgbe_mac_X540 ||
+                            hw->mac.type == ixgbe_mac_X550 ||
+                            hw->mac.type == ixgbe_mac_X550EM_x) {
                                 ixgbe->intr_throttling[0] =
                                     ixgbe->intr_throttling[0] & 0xFF8;
                         }
 
                         for (i = 0; i < MAX_INTR_VECTOR; i++)