valid = 1;
                else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)
                        || IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)
-                       || IS_QLA27XX(ha))
+                       || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                        valid = 1;
                if (!valid) {
                        ql_log(ql_log_warn, vha, 0x7065,
        if (IS_NOCACHE_VPD_TYPE(ha)) {
                faddr = ha->flt_region_vpd << 2;
 
-               if (IS_QLA27XX(ha) &&
+               if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
                    qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
                        faddr = ha->flt_region_vpd_sec << 2;
 
                ql_log(ql_log_info, vha, 0x706f,
                    "Issuing MPI reset.\n");
 
-               if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        uint32_t idc_control;
 
                        qla83xx_idc_lock(vha, 0);
                        continue;
                if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw)))
                        continue;
-               if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw))
+               if (iter->is4GBp_only == 0x27 &&
+                   (!IS_QLA27XX(vha->hw) || !IS_QLA28XX(ha)))
                        continue;
 
                sysfs_remove_bin_file(&host->shost_gendev.kobj,
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n",
        struct qla_hw_data *ha = vha->hw;
 
        if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) &&
-           !IS_QLA27XX(ha))
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%s\n",
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%s\n",
        int mode = QLA_SET_DATA_RATE_LR;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA27XX(vha->hw)) {
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) {
                ql_log(ql_log_warn, vha, 0x70d8,
                    "Speed setting not supported \n");
                return -EINVAL;
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return scnprintf(buf, PAGE_SIZE, "\n");
 
        return scnprintf(buf, PAGE_SIZE, "%llx\n",
        case PORT_SPEED_32GB:
                speed = FC_PORTSPEED_32GBIT;
                break;
+       case PORT_SPEED_64GB:
+               speed = FC_PORTSPEED_64GBIT;
+               break;
        }
        fc_host_speed(shost) = speed;
 }
        else if (IS_QLA27XX(ha))
                speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT |
                    FC_PORTSPEED_8GBIT;
+       else if (IS_QLA28XX(ha))
+               speed = FC_PORTSPEED_64GBIT | FC_PORTSPEED_32GBIT |
+                   FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT;
        else
                speed = FC_PORTSPEED_1GBIT;
        fc_host_supported_speeds(vha->host) = speed;
 
                    start == (ha->flt_region_fw * 4))
                        valid = 1;
                else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
-                   IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha))
+                   IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+                   IS_QLA28XX(ha))
                        valid = 1;
                if (!valid) {
                        ql_log(ql_log_warn, vha, 0x7058,
        struct qla_hw_data *ha = vha->hw;
        struct qla_flash_update_caps cap;
 
-       if (!(IS_QLA27XX(ha)))
+       if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
                return -EPERM;
 
        memset(&cap, 0, sizeof(cap));
        uint64_t online_fw_attr = 0;
        struct qla_flash_update_caps cap;
 
-       if (!(IS_QLA27XX(ha)))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return -EPERM;
 
        memset(&cap, 0, sizeof(cap));
        uint8_t domain, area, al_pa, state;
        int rval;
 
-       if (!(IS_QLA27XX(ha)))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return -EPERM;
 
        memset(&bbcr, 0, sizeof(bbcr));
        int rval;
        struct qla_dport_diag *dd;
 
-       if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+       if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+           !IS_QLA28XX(vha->hw))
                return -EPERM;
 
        dd = kmalloc(sizeof(*dd), GFP_KERNEL);
 
                        return rval;
                }
                for (j = 0; j < dwords; j++) {
-                       ram[i + j] = IS_QLA27XX(ha) ?
+                       ram[i + j] =
+                           (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
                            chunk[j] : swab32(chunk[j]);
                }
        }
                        return rval;
                }
                for (j = 0; j < dwords; j++) {
-                       ram[i + j] = IS_QLA27XX(ha) ?
+                       ram[i + j] =
+                           (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
                            chunk[j] : swab32(chunk[j]);
                }
        }
        struct qla2xxx_mq_chain *mq = ptr;
        device_reg_t *reg;
 
-       if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha))
                return ptr;
 
        mq = ptr;
 
 #define QLA27XX_IMG_STATUS_VER_MAJOR   0x01
 #define QLA27XX_IMG_STATUS_VER_MINOR    0x00
 #define QLA27XX_IMG_STATUS_SIGN   0xFACEFADE
+#define QLA28XX_IMG_STATUS_SIGN    0xFACEFADF
 #define QLA27XX_PRIMARY_IMAGE  1
 #define QLA27XX_SECONDARY_IMAGE    2
 
 #define FDMI_PORT_SPEED_8GB            0x10
 #define FDMI_PORT_SPEED_16GB           0x20
 #define FDMI_PORT_SPEED_32GB           0x40
+#define FDMI_PORT_SPEED_64GB           0x80
 #define FDMI_PORT_SPEED_UNKNOWN                0x8000
 
 #define FC_CLASS_2     0x04
 #define QLA_MQ_SIZE 32
 #define QLA_MAX_QUEUES 256
 #define ISP_QUE_REG(ha, id) \
-       ((ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? \
+       ((ha->mqenable || IS_QLA83XX(ha) || \
+         IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? \
         ((void __iomem *)ha->mqiobase + (QLA_QUE_PAGE * id)) :\
         ((void __iomem *)ha->iobase))
 #define QLA_REQ_QUE_ID(tag) \
 #define PORT_SPEED_8GB  0x04
 #define PORT_SPEED_16GB 0x05
 #define PORT_SPEED_32GB 0x06
+#define PORT_SPEED_64GB 0x07
 #define PORT_SPEED_10GB        0x13
        uint16_t        link_data_rate;         /* F/W operating speed */
        uint16_t        set_data_rate;          /* Set by user */
 #define PCI_DEVICE_ID_QLOGIC_ISP2071   0x2071
 #define PCI_DEVICE_ID_QLOGIC_ISP2271   0x2271
 #define PCI_DEVICE_ID_QLOGIC_ISP2261   0x2261
+#define PCI_DEVICE_ID_QLOGIC_ISP2061   0x2061
+#define PCI_DEVICE_ID_QLOGIC_ISP2081   0x2081
+#define PCI_DEVICE_ID_QLOGIC_ISP2089   0x2089
+#define PCI_DEVICE_ID_QLOGIC_ISP2281   0x2281
+#define PCI_DEVICE_ID_QLOGIC_ISP2289   0x2289
 
        uint32_t        isp_type;
 #define DT_ISP2100                      BIT_0
 #define DT_ISP2071                     BIT_19
 #define DT_ISP2271                     BIT_20
 #define DT_ISP2261                     BIT_21
-#define DT_ISP_LAST                    (DT_ISP2261 << 1)
+#define DT_ISP2061                     BIT_22
+#define DT_ISP2081                     BIT_23
+#define DT_ISP2089                     BIT_24
+#define DT_ISP2281                     BIT_25
+#define DT_ISP2289                     BIT_26
+#define DT_ISP_LAST                    (DT_ISP2289 << 1)
 
        uint32_t        device_type;
 #define DT_T10_PI                       BIT_25
 #define IS_QLA2071(ha) (DT_MASK(ha) & DT_ISP2071)
 #define IS_QLA2271(ha) (DT_MASK(ha) & DT_ISP2271)
 #define IS_QLA2261(ha) (DT_MASK(ha) & DT_ISP2261)
+#define IS_QLA2081(ha) (DT_MASK(ha) & DT_ISP2081)
+#define IS_QLA2281(ha) (DT_MASK(ha) & DT_ISP2281)
 
 #define IS_QLA23XX(ha)  (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
                        IS_QLA6312(ha) || IS_QLA6322(ha))
 #define IS_QLA83XX(ha) (IS_QLA2031(ha) || IS_QLA8031(ha))
 #define IS_QLA84XX(ha)  (IS_QLA8432(ha))
 #define IS_QLA27XX(ha)  (IS_QLA2071(ha) || IS_QLA2271(ha) || IS_QLA2261(ha))
+#define IS_QLA28XX(ha) (IS_QLA2081(ha) || IS_QLA2281(ha))
 #define IS_QLA24XX_TYPE(ha)     (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
                                IS_QLA84XX(ha))
 #define IS_CNA_CAPABLE(ha)     (IS_QLA81XX(ha) || IS_QLA82XX(ha) || \
 #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
                                IS_QLA25XX(ha) || IS_QLA81XX(ha) || \
                                IS_QLA82XX(ha) || IS_QLA83XX(ha) || \
-                               IS_QLA8044(ha) || IS_QLA27XX(ha))
+                               IS_QLA8044(ha) || IS_QLA27XX(ha) || \
+                               IS_QLA28XX(ha))
 #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
-                               IS_QLA27XX(ha))
+                               IS_QLA27XX(ha) || IS_QLA28XX(ha))
 #define IS_NOPOLLING_TYPE(ha)  (IS_QLA81XX(ha) && (ha)->flags.msix_enabled)
 #define IS_FAC_REQUIRED(ha)    (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
-                               IS_QLA27XX(ha))
+                               IS_QLA27XX(ha) || IS_QLA28XX(ha))
 #define IS_NOCACHE_VPD_TYPE(ha)        (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
-                               IS_QLA27XX(ha))
+                               IS_QLA27XX(ha) || IS_QLA28XX(ha))
 #define IS_ALOGIO_CAPABLE(ha)  (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
 
 #define IS_T10_PI_CAPABLE(ha)   ((ha)->device_type & DT_T10_PI)
 #define HAS_EXTENDED_IDS(ha)    ((ha)->device_type & DT_EXTENDED_IDS)
 #define IS_CT6_SUPPORTED(ha)   ((ha)->device_type & DT_CT6_SUPPORTED)
 #define IS_MQUE_CAPABLE(ha)    ((ha)->mqenable || IS_QLA83XX(ha) || \
-                               IS_QLA27XX(ha))
-#define IS_BIDI_CAPABLE(ha)    ((IS_QLA25XX(ha) || IS_QLA2031(ha)))
+                               IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_BIDI_CAPABLE(ha) \
+    (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
 /* Bit 21 of fw_attributes decides the MCTP capabilities */
 #define IS_MCTP_CAPABLE(ha)    (IS_QLA2031(ha) && \
                                ((ha)->fw_attributes_ext[0] & BIT_0))
 #define IS_PI_UNINIT_CAPABLE(ha)       (IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_PI_IPGUARD_CAPABLE(ha)      (IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_PI_DIFB_DIX0_CAPABLE(ha)    (0)
-#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha)        (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha)        (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+                                       IS_QLA28XX(ha))
 #define IS_PI_SPLIT_DET_CAPABLE(ha)    (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
     (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
-#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+                               IS_QLA28XX(ha))
 #define IS_TGT_MODE_CAPABLE(ha)        (ha->tgt.atio_q_length)
-#define IS_SHADOW_REG_CAPABLE(ha)  (IS_QLA27XX(ha))
-#define IS_DPORT_CAPABLE(ha)  (IS_QLA83XX(ha) || IS_QLA27XX(ha))
-#define IS_FAWWN_CAPABLE(ha)   (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_SHADOW_REG_CAPABLE(ha)  (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_DPORT_CAPABLE(ha)  (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+                               IS_QLA28XX(ha))
+#define IS_FAWWN_CAPABLE(ha)   (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+                               IS_QLA28XX(ha))
 #define IS_EXCHG_OFFLD_CAPABLE(ha) \
-       (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
 #define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
-       (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
+        IS_QLA27XX(ha) || IS_QLA28XX(ha))
 #define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
-       IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
 
        /* HBA serial number */
        uint8_t         serial0;
 #define OPTROM_SIZE_81XX       0x400000
 #define OPTROM_SIZE_82XX       0x800000
 #define OPTROM_SIZE_83XX       0x1000000
+#define OPTROM_SIZE_28XX       0x2000000
 
 #define OPTROM_BURST_SIZE      0x1000
 #define OPTROM_BURST_DWORDS    (OPTROM_BURST_SIZE / 4)
 #define AUTO_DETECT_SFP_SUPPORT(_vha)\
        (ql2xautodetectsfp && !_vha->vp_idx &&          \
        (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\
-       IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw)))
+       IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \
+        IS_QLA28XX(_vha->hw)))
 
 #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \
-       (IS_QLA27XX(_ha) || IS_QLA83XX(_ha)))
+       (IS_QLA27XX(_ha) || IS_QLA28XX(_ha) || IS_QLA83XX(_ha)))
 
 #define SAVE_TOPO(_ha) { \
        if (_ha->current_topology)                              \
 
        int rc = 0;
        unsigned long num_act_qp;
 
-       if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) {
+       if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))) {
                pr_err("host%ld: this adapter does not support Multi Q.",
                    vha->host_no);
                return -EINVAL;
        struct qla_hw_data *ha = vha->hw;
 
        if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-           !IS_QLA27XX(ha))
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                goto out;
        if (!ha->fce)
                goto out;
        ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess",
                S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops);
 
-       if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+       if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
                ha->tgt.dfs_naqp = debugfs_create_file("naqp",
                    0400, ha->dfs_dir, vha, &dfs_naqp_ops);
 out:
 
 
 #define FARX_ACCESS_FLASH_CONF_81XX    0x7FFD0000
 #define FARX_ACCESS_FLASH_DATA_81XX    0x7F800000
+#define FARX_ACCESS_FLASH_CONF_28XX    0x7FFD0000
+#define FARX_ACCESS_FLASH_DATA_28XX    0x7F7D0000
 
 /* FCP priority config defines *************************************/
 /* operations */
 #define FA_NPIV_CONF1_ADDR_81  0xD2000
 
 /* 83XX Flash locations -- occupies second 8MB region. */
-#define FA_FLASH_LAYOUT_ADDR_83        0xFC400
+#define FA_FLASH_LAYOUT_ADDR_83        (0x3F1000/4)
+#define FA_FLASH_LAYOUT_ADDR_28        (0x11000/4)
 
 #endif
 
        if (IS_CNA_CAPABLE(ha))
                eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_10GB);
-       else if (IS_QLA27XX(ha))
+       else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_32GB|
                    FDMI_PORT_SPEED_16GB|
        if (IS_CNA_CAPABLE(ha))
                eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_10GB);
-       else if (IS_QLA27XX(ha))
+       else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                eiter->a.sup_speed = cpu_to_be32(
                    FDMI_PORT_SPEED_32GB|
                    FDMI_PORT_SPEED_16GB|
 
        if (IS_FWI2_CAPABLE(ha)) {
                /* Allocate memory for Fibre Channel Event Buffer. */
                if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-                   !IS_QLA27XX(ha))
+                   !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                        goto try_eft;
 
                if (ha->fce)
                mem_size = (ha->fw_memory_size - 0x11000 + 1) *
                    sizeof(uint16_t);
        } else if (IS_FWI2_CAPABLE(ha)) {
-               if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                        fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
                else if (IS_QLA81XX(ha))
                        fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
                mem_size = (ha->fw_memory_size - 0x100000 + 1) *
                    sizeof(uint32_t);
                if (ha->mqenable) {
-                       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+                       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) &&
+                           !IS_QLA28XX(ha))
                                mq_size = sizeof(struct qla2xxx_mq_chain);
                        /*
                         * Allocate maximum buffer size for all queues.
                        mq_size += ha->tgt.atio_q_length * sizeof(request_t);
                /* Allocate memory for Fibre Channel Event Buffer. */
                if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-                   !IS_QLA27XX(ha))
+                   !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                        goto try_eft;
 
                fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
                eft_size = EFT_SIZE;
        }
 
-       if (IS_QLA27XX(ha)) {
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                if (!ha->fw_dump_template) {
                        ql_log(ql_log_warn, vha, 0x00ba,
                            "Failed missing fwdump template\n");
                            "Allocated (%d KB) for firmware dump.\n",
                            dump_size / 1024);
 
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                return;
 
                        ha->fw_dump->signature[0] = 'Q';
                        if (rval == QLA_SUCCESS) {
                                qla24xx_detect_sfp(vha);
 
-                               if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) &&
+                               if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                                   IS_QLA28XX(ha)) &&
                                    (ha->zio_mode == QLA_ZIO_MODE_6))
                                        qla27xx_set_zio_threshold(vha,
                                            ha->last_zio_threshold);
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
        }
 
-       if (IS_QLA27XX(ha))
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                ha->flags.fac_supported = 1;
        else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
                uint32_t size;
                            ha->fw_major_version, ha->fw_minor_version,
                            ha->fw_subminor_version);
 
-                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                           IS_QLA28XX(ha)) {
                                ha->flags.fac_supported = 0;
                                rval = QLA_SUCCESS;
                        }
 
        /* Move PUREX, ABTS RX & RIDA to ATIOQ */
        if (ql2xmvasynctoatio &&
-           (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
+           (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
                if (qla_tgt_mode_enabled(vha) ||
                    qla_dual_mode_enabled(vha))
                        ha->fw_options[2] |= BIT_11;
                        ha->fw_options[2] &= ~BIT_11;
        }
 
-       if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                /*
                 * Tell FW to track each exchange to prevent
                 * driver from using stale exchange.
        if (IS_SHADOW_REG_CAPABLE(ha))
                icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29);
 
-       if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS);
                icb->rid = cpu_to_le16(rid);
                if (ha->flags.msix_enabled) {
        uint32_t *wptr;
        uint32_t cnt, chksum, size;
        struct qla_hw_data *ha = vha->hw;
+       uint32_t signature;
 
        valid_pri_image = valid_sec_image = 1;
        ha->active_image = 0;
        qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
            ha->flt_region_img_status_pri, size);
 
-       if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
+       signature = le32_to_cpu(pri_image_status.signature);
+       if (signature != QLA27XX_IMG_STATUS_SIGN &&
+           signature != QLA28XX_IMG_STATUS_SIGN) {
                ql_dbg(ql_dbg_init, vha, 0x018b,
                    "Primary image signature (0x%x) not valid\n",
                    pri_image_status.signature);
        qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
            ha->flt_region_img_status_sec, size);
 
-       if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
+       signature = le32_to_cpu(sec_image_status.signature);
+       if (signature != QLA27XX_IMG_STATUS_SIGN &&
+           signature != QLA28XX_IMG_STATUS_SIGN) {
                ql_dbg(ql_dbg_init, vha, 0x018d,
                    "Secondary image signature(0x%x) not valid\n",
                    sec_image_status.signature);
        dcode = (uint32_t *)req->ring;
        *srisc_addr = 0;
 
-       if (IS_QLA27XX(ha) &&
+       if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
            qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
                faddr = ha->flt_region_fw_sec;
 
                segments--;
        }
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return rval;
 
        if (ha->fw_dump_template)
                segments--;
        }
 
-       if (!IS_QLA27XX(ha))
+       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return rval;
 
        if (ha->fw_dump_template)
                ha->login_retry_count = ql2xloginretrycount;
 
        /* if not running MSI-X we need handshaking on interrupts */
-       if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
+       if (!vha->hw->flags.msix_enabled &&
+           (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)))
                icb->firmware_options_2 |= cpu_to_le32(BIT_22);
 
        /* Enable ZIO. */
        /* N2N: driver will initiate Login instead of FW */
        icb->firmware_options_3 |= BIT_8;
 
-       if (IS_QLA27XX(ha)) {
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                icb->firmware_options_3 |= BIT_8;
                ql_dbg(ql_log_info, vha, 0x0075,
                    "Enabling direct connection.\n");
                qpair->msix->in_use = 1;
                list_add_tail(&qpair->qp_list_elem, &vha->qp_list);
                qpair->pdev = ha->pdev;
-               if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+               if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
                        qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
 
                mutex_unlock(&ha->mq_lock);
 
                        req->ring_ptr++;
 
                /* Set chip new ring index. */
-               if (ha->mqenable || IS_QLA27XX(ha)) {
+               if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        WRT_REG_DWORD(req->req_q_in, req->ring_index);
                } else if (IS_QLA83XX(ha)) {
                        WRT_REG_DWORD(req->req_q_in, req->ring_index);
        if (req->cnt < req_cnt + 2) {
                if (qpair->use_shadow_reg)
                        cnt = *req->out_ptr;
-               else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+               else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                   IS_QLA28XX(ha))
                        cnt = RD_REG_DWORD(®->isp25mq.req_q_out);
                else if (IS_P3P_TYPE(ha))
                        cnt = RD_REG_DWORD(®->isp82.req_q_out);
 
                break;
 
        case MBA_SYSTEM_ERR:            /* System Error */
-               mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ?
+               mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                   IS_QLA28XX(ha)) ?
                        RD_REG_WORD(®24->mailbox7) : 0;
                ql_log(ql_log_warn, vha, 0x5003,
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
                        qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
                        break;
                case ABTS_RECV_24XX:
-                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                           IS_QLA28XX(ha)) {
                                /* ensure that the ATIO queue is empty */
                                qlt_handle_abts_recv(vha, rsp,
                                    (response_t *)pkt);
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
        if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-           !IS_QLA27XX(ha))
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return;
 
        rval = QLA_SUCCESS;
        }
 
        /* Enable MSI-X vector for response queue update for queue 0 */
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                if (ha->msixbase && ha->mqiobase &&
                    (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
                     ql2xmqsupport))
        /* If possible, enable MSI-X. */
        if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
            !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
-           !IS_QLAFX00(ha) && !IS_QLA27XX(ha)))
+           !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)))
                goto skip_msi;
 
        if (ql2xenablemsix == 2)
 
        if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
            !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) &&
-           !IS_QLA27XX(ha))
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                goto skip_msi;
 
        ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI);
 
 {
        uint16_t mb4 = BIT_0;
 
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mb4 |= ha->long_range_distance << LR_DIST_FW_POS;
 
        return mb4;
 {
        uint16_t mb4 = BIT_0;
 
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                struct nvram_81xx *nv = ha->nvram;
 
                mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features);
                mcp->mb[4] = 0;
                ha->flags.using_lr_setting = 0;
                if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
-                   IS_QLA27XX(ha)) {
+                   IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        if (ql2xautodetectsfp) {
                                if (ha->flags.detected_lr_sfp) {
                                        mcp->mb[4] |=
                        }
                }
 
-               if (ql2xnvmeenable && IS_QLA27XX(ha))
+               if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha)))
                        mcp->mb[4] |= NVME_ENABLE_FLAG;
 
-               if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        struct nvram_81xx *nv = ha->nvram;
                        /* set minimum speed if specified in nvram */
                        if (nv->min_link_speed >= 2 &&
                            "fw_ability_mask=%x.\n", ha->fw_ability_mask);
                        ql_dbg(ql_dbg_mbx, vha, 0x1027,
                            "exchanges=%x.\n", mcp->mb[1]);
-                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                           IS_QLA28XX(ha)) {
                                ha->max_speed_sup = mcp->mb[2] & BIT_0;
                                ql_dbg(ql_dbg_mbx, vha, 0x119b,
                                    "Maximum speed supported=%s.\n",
                mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
        if (IS_FWI2_CAPABLE(ha))
                mcp->in_mb |= MBX_17|MBX_16|MBX_15;
-       if (IS_QLA27XX(ha))
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->in_mb |=
                    MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
                    MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8;
                }
        }
 
-       if (IS_QLA27XX(ha)) {
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                ha->mpi_version[0] = mcp->mb[10] & 0xff;
                ha->mpi_version[1] = mcp->mb[11] >> 8;
                ha->mpi_version[2] = mcp->mb[11] & 0xff;
                mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
        if (IS_FWI2_CAPABLE(vha->hw))
                mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
-       if (IS_QLA27XX(vha->hw))
+       if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
                mcp->in_mb |= MBX_15;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
                        }
                }
 
-               if (IS_QLA27XX(vha->hw))
+               if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
                        vha->bbcr = mcp->mb[15];
        }
 
        }
        /* 1 and 2 should normally be captured. */
        mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                /* mb3 is additional info about the installed SFP. */
                mcp->in_mb  |= MBX_3;
        mcp->buf_size = size;
                    "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n",
                    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]);
        } else {
-               if (IS_QLA27XX(ha)) {
+               if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
                                ql_dbg(ql_dbg_mbx, vha, 0x119d,
                                    "Invalid SFP/Validation Failed\n");
                /*EMPTY*/
                ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
        } else {
-               if (IS_QLA27XX(ha)) {
+               if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
                                ql_dbg(ql_dbg_mbx, vha, 0x119e,
                                    "Invalid SFP/Validation Failed\n");
        mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || IS_QLA27XX(vha->hw))
+       if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
+           IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->in_mb |= MBX_12;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
                ha->orig_fw_iocb_count = mcp->mb[10];
                if (ha->flags.npiv_supported)
                        ha->max_npiv_vports = mcp->mb[11];
-               if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+               if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+                   IS_QLA28XX(ha))
                        ha->fw_max_fcf_count = mcp->mb[12];
        }
 
        mbx_cmd_t *mcp = &mc;
 
        if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
-           !IS_QLA27XX(vha->hw))
+           !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182,
        mbx_cmd_t *mcp = &mc;
 
        if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
-           !IS_QLA27XX(vha->hw))
+           !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185,
            "Entered %s.\n", __func__);
 
        if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) &&
-           !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+           !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+           !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        if (unlikely(pci_channel_offline(vha->hw->pdev)))
        mcp->mb[12] = req->qos;
        mcp->mb[11] = req->vp_idx;
        mcp->mb[13] = req->rid;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->mb[15] = 0;
 
        mcp->mb[4] = req->id;
        mcp->flags = MBX_DMA_OUT;
        mcp->tov = MBX_TOV_SECONDS * 2;
 
-       if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha))
                mcp->in_mb |= MBX_1;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                mcp->out_mb |= MBX_15;
                /* debug q create issue in SR-IOV */
                mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
        spin_lock_irqsave(&ha->hardware_lock, flags);
        if (!(req->options & BIT_0)) {
                WRT_REG_DWORD(req->req_q_in, 0);
-               if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+               if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                        WRT_REG_DWORD(req->req_q_out, 0);
        }
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        mcp->mb[5] = rsp->length;
        mcp->mb[14] = rsp->msix->entry;
        mcp->mb[13] = rsp->rid;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->mb[15] = 0;
 
        mcp->mb[4] = rsp->id;
        if (IS_QLA81XX(ha)) {
                mcp->out_mb |= MBX_12|MBX_11|MBX_10;
                mcp->in_mb |= MBX_1;
-       } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10;
                mcp->in_mb |= MBX_1;
                /* debug q create issue in SR-IOV */
        spin_lock_irqsave(&ha->hardware_lock, flags);
        if (!(rsp->options & BIT_0)) {
                WRT_REG_DWORD(rsp->rsp_q_out, 0);
-               if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+               if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                        WRT_REG_DWORD(rsp->rsp_q_in, 0);
        }
 
            "Entered %s.\n", __func__);
 
        if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
-           !IS_QLA27XX(vha->hw))
+           !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
        mbx_cmd_t *mcp = &mc;
 
        if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
-           !IS_QLA27XX(vha->hw))
+           !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df,
        mbx_cmd_t *mcp = &mc;
 
        if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
-           !IS_QLA27XX(vha->hw))
+           !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
 
        mcp->out_mb = MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->in_mb |= MBX_4|MBX_3;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        mcp->mb[1] = QLA_GET_DATA_RATE;
        mcp->out_mb = MBX_1|MBX_0;
        mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                mcp->in_mb |= MBX_3;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
            "Entered %s.\n", __func__);
 
        if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) &&
-           !IS_QLA27XX(ha))
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return QLA_FUNCTION_FAILED;
        mcp->mb[0] = MBC_GET_PORT_CONFIG;
        mcp->out_mb = MBX_0;
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130,
        struct qla_hw_data *ha = vha->hw;
        unsigned long retry_max_time = jiffies + (2 * HZ);
 
-       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__);
        mbx_cmd_t *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA83XX(ha))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
        mbx_cmd_t *mcp = &mc;
        dma_addr_t dd_dma;
 
-       if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+       if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+           !IS_QLA28XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
 
        qla_cpu_update(rsp->qpair, raw_smp_processor_id());
        ha->base_qpair->pdev = ha->pdev;
 
-       if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+       if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
                ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
 }
 
                ha->device_type |= DT_T10_PI;
                ha->fw_srisc_address = RISC_START_ADDRESS_2400;
                break;
+       case PCI_DEVICE_ID_QLOGIC_ISP2081:
+       case PCI_DEVICE_ID_QLOGIC_ISP2089:
+               ha->isp_type |= DT_ISP2081;
+               ha->device_type |= DT_ZIO_SUPPORTED;
+               ha->device_type |= DT_FWI2;
+               ha->device_type |= DT_IIDMA;
+               ha->device_type |= DT_T10_PI;
+               ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+               break;
+       case PCI_DEVICE_ID_QLOGIC_ISP2281:
+       case PCI_DEVICE_ID_QLOGIC_ISP2289:
+               ha->isp_type |= DT_ISP2281;
+               ha->device_type |= DT_ZIO_SUPPORTED;
+               ha->device_type |= DT_FWI2;
+               ha->device_type |= DT_IIDMA;
+               ha->device_type |= DT_T10_PI;
+               ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+               break;
        }
 
        if (IS_QLA82XX(ha))
        else {
                /* Get adapter physical port no from interrupt pin register. */
                pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);
-               if (IS_QLA27XX(ha))
+               if (IS_QLA25XX(ha) || IS_QLA2031(ha) ||
+                   IS_QLA27XX(ha) || IS_QLA28XX(ha))
                        ha->port_no--;
                else
                        ha->port_no = !(ha->port_no & 1);
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8044 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2071 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2271 ||
-           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261) {
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2081 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2281 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2089 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2289) {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
                mem_only = 1;
                ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
 
        /* Set EEH reset type to fundamental if required by hba */
        if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha) ||
-           IS_QLA83XX(ha) || IS_QLA27XX(ha))
+           IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                pdev->needs_freset = 1;
 
        ha->prev_topology = 0;
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
                ha->nvram_conf_off = ~0;
                ha->nvram_data_off = ~0;
+       } else if (IS_QLA28XX(ha)) {
+               ha->portnum = PCI_FUNC(ha->pdev->devfn);
+               ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400;
+               ha->mbx_count = MAILBOX_REGISTER_COUNT;
+               req_length = REQUEST_ENTRY_CNT_24XX;
+               rsp_length = RESPONSE_ENTRY_CNT_2300;
+               ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
+               ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
+               ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
+               ha->gid_list_info_size = 8;
+               ha->optrom_size = OPTROM_SIZE_28XX;
+               ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
+               ha->isp_ops = &qla27xx_isp_ops;
+               ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_28XX;
+               ha->flash_data_off = FARX_ACCESS_FLASH_DATA_28XX;
+               ha->nvram_conf_off = ~0;
+               ha->nvram_data_off = ~0;
        }
 
        ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
        req->req_q_out = &ha->iobase->isp24.req_q_out;
        rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
        rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
-       if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
                req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
                rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
        if (ha->eft)
                qla2x00_disable_eft_trace(vha);
 
-       if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                if (ha->flags.fw_started)
                        qla2x00_abort_isp_cleanup(vha);
        } else {
                if (ha->mqiobase)
                        iounmap(ha->mqiobase);
 
-               if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && ha->msixbase)
+               if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
+                   ha->msixbase)
                        iounmap(ha->msixbase);
        }
 }
        }
        qla2x00_wait_for_hba_ready(base_vha);
 
-       if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                if (ha->flags.fw_started)
                        qla2x00_abort_isp_cleanup(base_vha);
        } else if (!IS_QLAFX00(ha)) {
                ha->npiv_info = NULL;
 
        /* Get consistent memory allocated for EX-INIT-CB. */
-       if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+       if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
                    &ha->ex_init_cb_dma);
                if (!ha->ex_init_cb)
        if (!vha->vp_idx &&
            (atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) &&
            (ha->zio_mode == QLA_ZIO_MODE_6) &&
-           (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
+           (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
                ql_log(ql_log_info, vha, 0x3002,
                    "Sched: Set ZIO exchange threshold to %d.\n",
                    ha->last_zio_threshold);
 
 /* Firmware interface routines. */
 
-#define FW_BLOBS       11
 #define FW_ISP21XX     0
 #define FW_ISP22XX     1
 #define FW_ISP2300     2
 #define FW_ISP2031     8
 #define FW_ISP8031     9
 #define FW_ISP27XX     10
+#define FW_ISP28XX     11
 
 #define FW_FILE_ISP21XX        "ql2100_fw.bin"
 #define FW_FILE_ISP22XX        "ql2200_fw.bin"
 #define FW_FILE_ISP2031        "ql2600_fw.bin"
 #define FW_FILE_ISP8031        "ql8300_fw.bin"
 #define FW_FILE_ISP27XX        "ql2700_fw.bin"
+#define FW_FILE_ISP28XX        "ql2800_fw.bin"
 
 
 static DEFINE_MUTEX(qla_fw_lock);
 
-static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
+static struct fw_blob qla_fw_blobs[] = {
        { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
        { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, },
        { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, },
        { .name = FW_FILE_ISP2031, },
        { .name = FW_FILE_ISP8031, },
        { .name = FW_FILE_ISP27XX, },
+       { .name = FW_FILE_ISP28XX, },
+       { .name = NULL, },
 };
 
 struct fw_blob *
                blob = &qla_fw_blobs[FW_ISP8031];
        } else if (IS_QLA27XX(ha)) {
                blob = &qla_fw_blobs[FW_ISP27XX];
+       } else if (IS_QLA28XX(ha)) {
+               blob = &qla_fw_blobs[FW_ISP28XX];
        } else {
                return NULL;
        }
 
+       if (!blob->name)
+               return NULL;
+
        mutex_lock(&qla_fw_lock);
        if (blob->fw)
                goto out;
                    "Failed to load firmware image (%s).\n", blob->name);
                blob->fw = NULL;
                blob = NULL;
-               goto out;
        }
 
 out:
 static void
 qla2x00_release_firmware(void)
 {
-       int idx;
+       struct fw_blob *blob;
 
        mutex_lock(&qla_fw_lock);
-       for (idx = 0; idx < FW_BLOBS; idx++)
-               release_firmware(qla_fw_blobs[idx].fw);
+       for (blob = qla_fw_blobs; blob->name; blob++)
+               release_firmware(blob->fw);
        mutex_unlock(&qla_fw_lock);
 }
 
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2071) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2271) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2261) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2061) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2081) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2281) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2089) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2289) },
        { 0 },
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
 
        } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
                *start = FA_FLASH_LAYOUT_ADDR_83;
                goto end;
+       } else if (IS_QLA28XX(ha)) {
+               *start = FA_FLASH_LAYOUT_ADDR_28;
+               goto end;
        }
        /* Begin with first PCI expansion ROM header. */
        buf = (uint8_t *)req->ring;
                                ha->flt_region_vpd = start;
                        break;
                case FLT_REG_VPD_2:
-                       if (!IS_QLA27XX(ha))
+                       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                break;
                        if (ha->port_no == 2)
                                ha->flt_region_vpd = start;
                        break;
                case FLT_REG_VPD_3:
-                       if (!IS_QLA27XX(ha))
+                       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                break;
                        if (ha->port_no == 3)
                                ha->flt_region_vpd = start;
                                ha->flt_region_nvram = start;
                        break;
                case FLT_REG_NVRAM_2:
-                       if (!IS_QLA27XX(ha))
+                       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                break;
                        if (ha->port_no == 2)
                                ha->flt_region_nvram = start;
                        break;
                case FLT_REG_NVRAM_3:
-                       if (!IS_QLA27XX(ha))
+                       if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                break;
                        if (ha->port_no == 3)
                                ha->flt_region_nvram = start;
                                ha->flt_region_nvram = start;
                        break;
                case FLT_REG_IMG_PRI_27XX:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_img_status_pri = start;
                        break;
                case FLT_REG_IMG_SEC_27XX:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_img_status_sec = start;
                        break;
                case FLT_REG_FW_SEC_27XX:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_fw_sec = start;
                        break;
                case FLT_REG_BOOTLOAD_SEC_27XX:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_boot_sec = start;
                        break;
                case FLT_REG_VPD_SEC_27XX_0:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_vpd_sec = start;
                        break;
                case FLT_REG_VPD_SEC_27XX_1:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_vpd_sec = start;
                        break;
                case FLT_REG_VPD_SEC_27XX_2:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_vpd_sec = start;
                        break;
                case FLT_REG_VPD_SEC_27XX_3:
-                       if (IS_QLA27XX(ha))
+                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                                ha->flt_region_vpd_sec = start;
                        break;
                }
        struct qla_hw_data *ha = vha->hw;
 
        if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
-           !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha))
+           !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                return QLA_SUCCESS;
 
        ret = qla2xxx_find_flt_start(vha, &flt_addr);
 
        /* Prepare burst-capable write on supported ISPs. */
        if ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
-           IS_QLA27XX(ha)) &&
+           IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
            !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) {
                optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
                    &optrom_dma, GFP_KERNEL);
 {
        uint32_t led_select_value = 0;
 
-       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
                goto out;
 
        if (ha->port_no == 0)
        uint16_t orig_led_cfg[6];
        uint32_t led_10_value, led_43_value;
 
-       if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha))
+       if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha) &&
+           !IS_QLA28XX(ha))
                return;
 
        if (!ha->beacon_blink_led)
                return;
 
-       if (IS_QLA27XX(ha)) {
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                qla2x00_write_ram_word(vha, 0x1003, 0x40000230);
                qla2x00_write_ram_word(vha, 0x1004, 0x40000230);
        } else if (IS_QLA2031(ha)) {
                        return QLA_FUNCTION_FAILED;
                }
 
-               if (IS_QLA2031(ha) || IS_QLA27XX(ha))
+               if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                        goto skip_gpio;
 
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
        ha->beacon_blink_led = 0;
 
-       if (IS_QLA2031(ha) || IS_QLA27XX(ha))
+       if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
                goto set_fw_options;
 
        if (IS_QLA8031(ha) || IS_QLA81XX(ha))
        struct qla_hw_data *ha = vha->hw;
 
        if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
-           IS_QLA27XX(ha))
+           IS_QLA27XX(ha) || IS_QLA28XX(ha))
                goto try_fast;
        if (offset & 0xfff)
                goto slow_read;
 
        dcode = mbuf;
        pcihdr = ha->flt_region_boot << 2;
-       if (IS_QLA27XX(ha) &&
+       if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
            qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
                pcihdr = ha->flt_region_boot_sec << 2;
 
        memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
        dcode = mbuf;
        faddr = ha->flt_region_fw;
-       if (IS_QLA27XX(ha) &&
+       if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
            qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
                faddr = ha->flt_region_fw_sec;
 
 
        RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
 
        if (ha->flags.msix_enabled) {
-               if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        if (IS_QLA2071(ha)) {
                                /* 4 ports Baker: Enable Interrupt Handshake */
                                icb->msix_atio = 0;
                }
        } else {
                /* INTx|MSI */
-               if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
                        icb->msix_atio = 0;
                        icb->firmware_options_2 |= BIT_26;
                        ql_dbg(ql_dbg_init, vha, 0xf072,
        if (!QLA_TGT_MODE_ENABLED())
                return;
 
-       if  ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if  ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+           IS_QLA28XX(ha)) {
                ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
                ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
        } else {