]> Git Repo - J-linux.git/commitdiff
Merge branch '5.11/scsi-postmerge' into 5.11/scsi-fixes
authorMartin K. Petersen <[email protected]>
Mon, 4 Jan 2021 18:27:39 +0000 (13:27 -0500)
committerMartin K. Petersen <[email protected]>
Mon, 4 Jan 2021 18:27:39 +0000 (13:27 -0500)
Merge two commits that had dependencies on other 5.11 trees (the block
and the irq trees respectively).

 - We reverted a megaraid_sas change in 5.10 due to missing block
   layer plumbing. Now that this is in place, reinstate the change.

 - The hisi_sas driver had a dependency on a driver core irq change
   that went in through Thomas' tree.

Signed-off-by: Martin K. Petersen <[email protected]>
1  2 
drivers/scsi/hisi_sas/hisi_sas.h
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/megaraid/megaraid_sas_base.c

index 2b28dd405600326de2d3c81e08ada7594efb3a8f,aa67807c56938879f4c63ec5260d9f9970a5a395..e821dd32dd28088e71119fd16c0bea526c37b2f3
@@@ -14,6 -14,7 +14,7 @@@
  #include <linux/debugfs.h>
  #include <linux/dmapool.h>
  #include <linux/iopoll.h>
+ #include <linux/irq.h>
  #include <linux/lcm.h>
  #include <linux/libata.h>
  #include <linux/mfd/syscon.h>
@@@ -243,6 -244,24 +244,6 @@@ struct hisi_sas_slot 
        u16     idx;
  };
  
 -#define HISI_SAS_DEBUGFS_REG(x) {#x, x}
 -
 -struct hisi_sas_debugfs_reg_lu {
 -      char *name;
 -      int off;
 -};
 -
 -struct hisi_sas_debugfs_reg {
 -      const struct hisi_sas_debugfs_reg_lu *lu;
 -      int count;
 -      int base_off;
 -      union {
 -              u32 (*read_global_reg)(struct hisi_hba *hisi_hba, u32 off);
 -              u32 (*read_port_reg)(struct hisi_hba *hisi_hba, int port,
 -                                   u32 off);
 -      };
 -};
 -
  struct hisi_sas_iost_itct_cache {
        u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ];
  };
@@@ -294,6 -313,7 +295,7 @@@ enum 
  
  struct hisi_sas_hw {
        int (*hw_init)(struct hisi_hba *hisi_hba);
+       int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
        void (*setup_itct)(struct hisi_hba *hisi_hba,
                           struct hisi_sas_device *device);
        int (*slot_index_alloc)(struct hisi_hba *hisi_hba,
                                           int delay_ms, int timeout_ms);
        void (*snapshot_prepare)(struct hisi_hba *hisi_hba);
        void (*snapshot_restore)(struct hisi_hba *hisi_hba);
 -      int (*set_bist)(struct hisi_hba *hisi_hba, bool enable);
 -      void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba,
 -                                   enum hisi_sas_debugfs_cache_type type,
 -                                   u32 *cache);
        int complete_hdr_size;
        struct scsi_host_template *sht;
 -
 -      const struct hisi_sas_debugfs_reg *debugfs_reg_array[DEBUGFS_REGS_NUM];
 -      const struct hisi_sas_debugfs_reg *debugfs_reg_port;
  };
  
  #define HISI_SAS_MAX_DEBUGFS_DUMP (50)
@@@ -393,6 -420,8 +395,8 @@@ struct hisi_hba 
        u32 refclk_frequency_mhz;
        u8 sas_addr[SAS_ADDR_SIZE];
  
+       int *irq_map; /* v2 hw */
        int n_phy;
        spinlock_t lock;
        struct semaphore sem;
@@@ -648,4 -677,7 +652,4 @@@ extern void hisi_sas_release_tasks(stru
  extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
  extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);
  extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);
 -extern void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba);
 -extern void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba);
 -extern void hisi_sas_debugfs_work_handler(struct work_struct *work);
  #endif
index b6d4419c32f2723c94d808f0ea7a911632dce562,061d65b8a28784f7ab86e558e401933dda28fc1a..cf0bfac920a8181d0c51c14d5ba67730a1957f7d
@@@ -591,7 -591,13 +591,7 @@@ static int hisi_sas_task_exec(struct sa
        dev = hisi_hba->dev;
  
        if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
 -              /*
 -               * For IOs from upper layer, it may already disable preempt
 -               * in the IO path, if disable preempt again in down(),
 -               * function schedule() will report schedule_bug(), so check
 -               * preemptible() before goto down().
 -               */
 -              if (!preemptible())
 +              if (!gfpflags_allow_blocking(gfp_flags))
                        return -EINVAL;
  
                down(&hisi_hba->sem);
@@@ -2614,6 -2620,13 +2614,13 @@@ err_out
        return NULL;
  }
  
+ static int hisi_sas_interrupt_preinit(struct hisi_hba *hisi_hba)
+ {
+       if (hisi_hba->hw->interrupt_preinit)
+               return hisi_hba->hw->interrupt_preinit(hisi_hba);
+       return 0;
+ }
  int hisi_sas_probe(struct platform_device *pdev,
                   const struct hisi_sas_hw *hw)
  {
                sha->sas_port[i] = &hisi_hba->port[i].sas_port;
        }
  
+       rc = hisi_sas_interrupt_preinit(hisi_hba);
+       if (rc)
+               goto err_out_ha;
        rc = scsi_add_host(shost, &pdev->dev);
        if (rc)
                goto err_out_ha;
  err_out_register_ha:
        scsi_remove_host(shost);
  err_out_ha:
 -      hisi_sas_debugfs_exit(hisi_hba);
        hisi_sas_free(hisi_hba);
        scsi_host_put(shost);
        return rc;
  }
  EXPORT_SYMBOL_GPL(hisi_sas_probe);
  
 -struct dentry *hisi_sas_debugfs_dir;
 -
 -static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
 -{
 -      int queue_entry_size = hisi_hba->hw->complete_hdr_size;
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      int i;
 -
 -      for (i = 0; i < hisi_hba->queue_count; i++)
 -              memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr,
 -                     hisi_hba->complete_hdr[i],
 -                     HISI_SAS_QUEUE_SLOTS * queue_entry_size);
 -}
 -
 -static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
 -{
 -      int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr);
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      int i;
 -
 -      for (i = 0; i < hisi_hba->queue_count; i++) {
 -              struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
 -              int j;
 -
 -              debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr;
 -              cmd_hdr = hisi_hba->cmd_hdr[i];
 -
 -              for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
 -                      memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j],
 -                             queue_entry_size);
 -      }
 -}
 -
 -static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      const struct hisi_sas_debugfs_reg *port =
 -              hisi_hba->hw->debugfs_reg_port;
 -      int i, phy_cnt;
 -      u32 offset;
 -      u32 *databuf;
 -
 -      for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) {
 -              databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data;
 -              for (i = 0; i < port->count; i++, databuf++) {
 -                      offset = port->base_off + 4 * i;
 -                      *databuf = port->read_port_reg(hisi_hba, phy_cnt,
 -                                                     offset);
 -              }
 -      }
 -}
 -
 -static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const struct hisi_sas_debugfs_reg *global =
 -                      hw->debugfs_reg_array[DEBUGFS_GLOBAL];
 -      int i;
 -
 -      for (i = 0; i < global->count; i++, databuf++)
 -              *databuf = global->read_global_reg(hisi_hba, 4 * i);
 -}
 -
 -static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const struct hisi_sas_debugfs_reg *axi =
 -                      hw->debugfs_reg_array[DEBUGFS_AXI];
 -      int i;
 -
 -      for (i = 0; i < axi->count; i++, databuf++)
 -              *databuf = axi->read_global_reg(hisi_hba,
 -                                              4 * i + axi->base_off);
 -}
 -
 -static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const struct hisi_sas_debugfs_reg *ras =
 -                      hw->debugfs_reg_array[DEBUGFS_RAS];
 -      int i;
 -
 -      for (i = 0; i < ras->count; i++, databuf++)
 -              *databuf = ras->read_global_reg(hisi_hba,
 -                                              4 * i + ras->base_off);
 -}
 -
 -static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache;
 -      void *databuf = hisi_hba->debugfs_itct[dump_index].itct;
 -      struct hisi_sas_itct *itct;
 -      int i;
 -
 -      hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE,
 -                                         cachebuf);
 -
 -      itct = hisi_hba->itct;
 -
 -      for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
 -              memcpy(databuf, itct, sizeof(struct hisi_sas_itct));
 -              databuf += sizeof(struct hisi_sas_itct);
 -      }
 -}
 -
 -static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
 -{
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      int max_command_entries = HISI_SAS_MAX_COMMANDS;
 -      void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache;
 -      void *databuf = hisi_hba->debugfs_iost[dump_index].iost;
 -      struct hisi_sas_iost *iost;
 -      int i;
 -
 -      hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE,
 -                                         cachebuf);
 -
 -      iost = hisi_hba->iost;
 -
 -      for (i = 0; i < max_command_entries; i++, iost++) {
 -              memcpy(databuf, iost, sizeof(struct hisi_sas_iost));
 -              databuf += sizeof(struct hisi_sas_iost);
 -      }
 -}
 -
 -static const char *
 -hisi_sas_debugfs_to_reg_name(int off, int base_off,
 -                           const struct hisi_sas_debugfs_reg_lu *lu)
 -{
 -      for (; lu->name; lu++) {
 -              if (off == lu->off - base_off)
 -                      return lu->name;
 -      }
 -
 -      return NULL;
 -}
 -
 -static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr,
 -                                     struct seq_file *s)
 -{
 -      const struct hisi_sas_debugfs_reg *reg = ptr;
 -      int i;
 -
 -      for (i = 0; i < reg->count; i++) {
 -              int off = i * 4;
 -              const char *name;
 -
 -              name = hisi_sas_debugfs_to_reg_name(off, reg->base_off,
 -                                                  reg->lu);
 -
 -              if (name)
 -                      seq_printf(s, "0x%08x 0x%08x %s\n", off,
 -                                 regs_val[i], name);
 -              else
 -                      seq_printf(s, "0x%08x 0x%08x\n", off,
 -                                 regs_val[i]);
 -      }
 -}
 -
 -static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_regs *global = s->private;
 -      struct hisi_hba *hisi_hba = global->hisi_hba;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL];
 -
 -      hisi_sas_debugfs_print_reg(global->data,
 -                                 reg_global, s);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_global_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_global_fops = {
 -      .open = hisi_sas_debugfs_global_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_regs *axi = s->private;
 -      struct hisi_hba *hisi_hba = axi->hisi_hba;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI];
 -
 -      hisi_sas_debugfs_print_reg(axi->data,
 -                                 reg_axi, s);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_axi_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_axi_fops = {
 -      .open = hisi_sas_debugfs_axi_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_regs *ras = s->private;
 -      struct hisi_hba *hisi_hba = ras->hisi_hba;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS];
 -
 -      hisi_sas_debugfs_print_reg(ras->data,
 -                                 reg_ras, s);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_ras_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_ras_fops = {
 -      .open = hisi_sas_debugfs_ras_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_port *port = s->private;
 -      struct hisi_sas_phy *phy = port->phy;
 -      struct hisi_hba *hisi_hba = phy->hisi_hba;
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port;
 -
 -      hisi_sas_debugfs_print_reg(port->data, reg_port, s);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_port_fops = {
 -      .open = hisi_sas_debugfs_port_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static void hisi_sas_show_row_64(struct seq_file *s, int index,
 -                               int sz, __le64 *ptr)
 -{
 -      int i;
 -
 -      /* completion header size not fixed per HW version */
 -      seq_printf(s, "index %04d:\n\t", index);
 -      for (i = 1; i <= sz / 8; i++, ptr++) {
 -              seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr));
 -              if (!(i % 2))
 -                      seq_puts(s, "\n\t");
 -      }
 -
 -      seq_puts(s, "\n");
 -}
 -
 -static void hisi_sas_show_row_32(struct seq_file *s, int index,
 -                               int sz, __le32 *ptr)
 -{
 -      int i;
 -
 -      /* completion header size not fixed per HW version */
 -      seq_printf(s, "index %04d:\n\t", index);
 -      for (i = 1; i <= sz / 4; i++, ptr++) {
 -              seq_printf(s, " 0x%08x", le32_to_cpu(*ptr));
 -              if (!(i % 4))
 -                      seq_puts(s, "\n\t");
 -      }
 -      seq_puts(s, "\n");
 -}
 -
 -static void hisi_sas_cq_show_slot(struct seq_file *s, int slot,
 -                                struct hisi_sas_debugfs_cq *debugfs_cq)
 -{
 -      struct hisi_sas_cq *cq = debugfs_cq->cq;
 -      struct hisi_hba *hisi_hba = cq->hisi_hba;
 -      __le32 *complete_hdr = debugfs_cq->complete_hdr +
 -                             (hisi_hba->hw->complete_hdr_size * slot);
 -
 -      hisi_sas_show_row_32(s, slot,
 -                           hisi_hba->hw->complete_hdr_size,
 -                           complete_hdr);
 -}
 -
 -static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
 -      int slot;
 -
 -      for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
 -              hisi_sas_cq_show_slot(s, slot, debugfs_cq);
 -      }
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_cq_fops = {
 -      .open = hisi_sas_debugfs_cq_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr)
 -{
 -      struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr;
 -      void *cmd_queue = debugfs_dq->hdr;
 -      __le32 *cmd_hdr = cmd_queue +
 -              sizeof(struct hisi_sas_cmd_hdr) * slot;
 -
 -      hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr);
 -}
 -
 -static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p)
 -{
 -      int slot;
 -
 -      for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
 -              hisi_sas_dq_show_slot(s, slot, s->private);
 -      }
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_dq_fops = {
 -      .open = hisi_sas_debugfs_dq_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_iost *debugfs_iost = s->private;
 -      struct hisi_sas_iost *iost = debugfs_iost->iost;
 -      int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
 -
 -      for (i = 0; i < max_command_entries; i++, iost++) {
 -              __le64 *data = &iost->qw0;
 -
 -              hisi_sas_show_row_64(s, i, sizeof(*iost), data);
 -      }
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_iost_fops = {
 -      .open = hisi_sas_debugfs_iost_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private;
 -      struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache;
 -      u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
 -      int i, tab_idx;
 -      __le64 *iost;
 -
 -      for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
 -              /*
 -               * Data struct of IOST cache:
 -               * Data[1]: BIT0~15: Table index
 -               *          Bit16:   Valid mask
 -               * Data[2]~[9]: IOST table
 -               */
 -              tab_idx = (iost_cache->data[1] & 0xffff);
 -              iost = (__le64 *)iost_cache;
 -
 -              hisi_sas_show_row_64(s, tab_idx, cache_size, iost);
 -      }
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_iost_cache_open(struct inode *inode,
 -                                          struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_iost_cache_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_iost_cache_fops = {
 -      .open = hisi_sas_debugfs_iost_cache_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
 -{
 -      int i;
 -      struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
 -      struct hisi_sas_itct *itct = debugfs_itct->itct;
 -
 -      for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
 -              __le64 *data = &itct->qw0;
 -
 -              hisi_sas_show_row_64(s, i, sizeof(*itct), data);
 -      }
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_itct_fops = {
 -      .open = hisi_sas_debugfs_itct_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
 +int hisi_sas_remove(struct platform_device *pdev)
  {
 -      struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private;
 -      struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache;
 -      u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
 -      int i, tab_idx;
 -      __le64 *itct;
 +      struct sas_ha_struct *sha = platform_get_drvdata(pdev);
 +      struct hisi_hba *hisi_hba = sha->lldd_ha;
 +      struct Scsi_Host *shost = sha->core.shost;
  
 -      for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
 -              /*
 -               * Data struct of ITCT cache:
 -               * Data[1]: BIT0~15: Table index
 -               *          Bit16:   Valid mask
 -               * Data[2]~[9]: ITCT table
 -               */
 -              tab_idx = itct_cache->data[1] & 0xffff;
 -              itct = (__le64 *)itct_cache;
 +      if (timer_pending(&hisi_hba->timer))
 +              del_timer(&hisi_hba->timer);
  
 -              hisi_sas_show_row_64(s, tab_idx, cache_size, itct);
 -      }
 +      sas_unregister_ha(sha);
 +      sas_remove_host(sha->core.shost);
  
 +      hisi_sas_free(hisi_hba);
 +      scsi_host_put(shost);
        return 0;
  }
 +EXPORT_SYMBOL_GPL(hisi_sas_remove);
  
 -static int hisi_sas_debugfs_itct_cache_open(struct inode *inode,
 -                                          struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_itct_cache_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_itct_cache_fops = {
 -      .open = hisi_sas_debugfs_itct_cache_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
 -{
 -      u64 *debugfs_timestamp;
 -      int dump_index = hisi_hba->debugfs_dump_index;
 -      struct dentry *dump_dentry;
 -      struct dentry *dentry;
 -      char name[256];
 -      int p;
 -      int c;
 -      int d;
 -
 -      snprintf(name, 256, "%d", dump_index);
 -
 -      dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
 -
 -      debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
 -
 -      debugfs_create_u64("timestamp", 0400, dump_dentry,
 -                         debugfs_timestamp);
 -
 -      debugfs_create_file("global", 0400, dump_dentry,
 -                         &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
 -                         &hisi_sas_debugfs_global_fops);
 -
 -      /* Create port dir and files */
 -      dentry = debugfs_create_dir("port", dump_dentry);
 -      for (p = 0; p < hisi_hba->n_phy; p++) {
 -              snprintf(name, 256, "%d", p);
 -
 -              debugfs_create_file(name, 0400, dentry,
 -                                  &hisi_hba->debugfs_port_reg[dump_index][p],
 -                                  &hisi_sas_debugfs_port_fops);
 -      }
 -
 -      /* Create CQ dir and files */
 -      dentry = debugfs_create_dir("cq", dump_dentry);
 -      for (c = 0; c < hisi_hba->queue_count; c++) {
 -              snprintf(name, 256, "%d", c);
 -
 -              debugfs_create_file(name, 0400, dentry,
 -                                  &hisi_hba->debugfs_cq[dump_index][c],
 -                                  &hisi_sas_debugfs_cq_fops);
 -      }
 -
 -      /* Create DQ dir and files */
 -      dentry = debugfs_create_dir("dq", dump_dentry);
 -      for (d = 0; d < hisi_hba->queue_count; d++) {
 -              snprintf(name, 256, "%d", d);
 -
 -              debugfs_create_file(name, 0400, dentry,
 -                                  &hisi_hba->debugfs_dq[dump_index][d],
 -                                  &hisi_sas_debugfs_dq_fops);
 -      }
 -
 -      debugfs_create_file("iost", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_iost[dump_index],
 -                          &hisi_sas_debugfs_iost_fops);
 -
 -      debugfs_create_file("iost_cache", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_iost_cache[dump_index],
 -                          &hisi_sas_debugfs_iost_cache_fops);
 -
 -      debugfs_create_file("itct", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_itct[dump_index],
 -                          &hisi_sas_debugfs_itct_fops);
 -
 -      debugfs_create_file("itct_cache", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_itct_cache[dump_index],
 -                          &hisi_sas_debugfs_itct_cache_fops);
 -
 -      debugfs_create_file("axi", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
 -                          &hisi_sas_debugfs_axi_fops);
 -
 -      debugfs_create_file("ras", 0400, dump_dentry,
 -                          &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
 -                          &hisi_sas_debugfs_ras_fops);
 -
 -      return;
 -}
 -
 -static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba)
 -{
 -      hisi_hba->hw->snapshot_prepare(hisi_hba);
 -
 -      hisi_sas_debugfs_snapshot_global_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_port_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_axi_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_ras_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_cq_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_dq_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_itct_reg(hisi_hba);
 -      hisi_sas_debugfs_snapshot_iost_reg(hisi_hba);
 -
 -      hisi_sas_debugfs_create_files(hisi_hba);
 -
 -      hisi_hba->hw->snapshot_restore(hisi_hba);
 -}
 +bool hisi_sas_debugfs_enable;
 +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable);
 +module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
 +MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
  
 -static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file,
 -                                                 const char __user *user_buf,
 -                                                 size_t count, loff_t *ppos)
 -{
 -      struct hisi_hba *hisi_hba = file->f_inode->i_private;
 -      char buf[8];
 +u32 hisi_sas_debugfs_dump_count = 1;
 +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count);
 +module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444);
 +MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
  
 -      if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
 -              return -EFAULT;
 -
 -      if (count > 8)
 -              return -EFAULT;
 -
 -      if (copy_from_user(buf, user_buf, count))
 -              return -EFAULT;
 -
 -      if (buf[0] != '1')
 -              return -EFAULT;
 -
 -      queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
 -
 -      return count;
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = {
 -      .write = &hisi_sas_debugfs_trigger_dump_write,
 -      .owner = THIS_MODULE,
 -};
 -
 -enum {
 -      HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0,
 -      HISI_SAS_BIST_LOOPBACK_MODE_SERDES,
 -      HISI_SAS_BIST_LOOPBACK_MODE_REMOTE,
 -};
 -
 -static const struct {
 -      int             value;
 -      char            *name;
 -} hisi_sas_debugfs_loop_linkrate[] = {
 -      { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" },
 -      { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" },
 -      { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" },
 -      { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" },
 -};
 -
 -static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_hba *hisi_hba = s->private;
 -      int i;
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) {
 -              int match = (hisi_hba->debugfs_bist_linkrate ==
 -                           hisi_sas_debugfs_loop_linkrate[i].value);
 -
 -              seq_printf(s, "%s%s%s ", match ? "[" : "",
 -                         hisi_sas_debugfs_loop_linkrate[i].name,
 -                         match ? "]" : "");
 -      }
 -      seq_puts(s, "\n");
 -
 -      return 0;
 -}
 -
 -static ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp,
 -                                                  const char __user *buf,
 -                                                  size_t count, loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      struct hisi_hba *hisi_hba = m->private;
 -      char kbuf[16] = {}, *pkbuf;
 -      bool found = false;
 -      int i;
 -
 -      if (hisi_hba->debugfs_bist_enable)
 -              return -EPERM;
 -
 -      if (count >= sizeof(kbuf))
 -              return -EOVERFLOW;
 -
 -      if (copy_from_user(kbuf, buf, count))
 -              return -EINVAL;
 -
 -      pkbuf = strstrip(kbuf);
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) {
 -              if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name,
 -                           pkbuf, 16)) {
 -                      hisi_hba->debugfs_bist_linkrate =
 -                              hisi_sas_debugfs_loop_linkrate[i].value;
 -                      found = true;
 -                      break;
 -              }
 -      }
 -
 -      if (!found)
 -              return -EINVAL;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode,
 -                                             struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_bist_linkrate_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = {
 -      .open = hisi_sas_debugfs_bist_linkrate_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_bist_linkrate_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static const struct {
 -      int             value;
 -      char            *name;
 -} hisi_sas_debugfs_loop_code_mode[] = {
 -      { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" },
 -      { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" },
 -      { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" },
 -      { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" },
 -      { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" },
 -      { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" },
 -      { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" },
 -      { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" },
 -      { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" },
 -      { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" },
 -      { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" },
 -      { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" },
 -};
 -
 -static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_hba *hisi_hba = s->private;
 -      int i;
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) {
 -              int match = (hisi_hba->debugfs_bist_code_mode ==
 -                           hisi_sas_debugfs_loop_code_mode[i].value);
 -
 -              seq_printf(s, "%s%s%s ", match ? "[" : "",
 -                         hisi_sas_debugfs_loop_code_mode[i].name,
 -                         match ? "]" : "");
 -      }
 -      seq_puts(s, "\n");
 -
 -      return 0;
 -}
 -
 -static ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp,
 -                                                   const char __user *buf,
 -                                                   size_t count,
 -                                                   loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      struct hisi_hba *hisi_hba = m->private;
 -      char kbuf[16] = {}, *pkbuf;
 -      bool found = false;
 -      int i;
 -
 -      if (hisi_hba->debugfs_bist_enable)
 -              return -EPERM;
 -
 -      if (count >= sizeof(kbuf))
 -              return -EINVAL;
 -
 -      if (copy_from_user(kbuf, buf, count))
 -              return -EOVERFLOW;
 -
 -      pkbuf = strstrip(kbuf);
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) {
 -              if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name,
 -                           pkbuf, 16)) {
 -                      hisi_hba->debugfs_bist_code_mode =
 -                              hisi_sas_debugfs_loop_code_mode[i].value;
 -                      found = true;
 -                      break;
 -              }
 -      }
 -
 -      if (!found)
 -              return -EINVAL;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode,
 -                                              struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_bist_code_mode_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = {
 -      .open = hisi_sas_debugfs_bist_code_mode_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_bist_code_mode_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp,
 -                                             const char __user *buf,
 -                                             size_t count, loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      struct hisi_hba *hisi_hba = m->private;
 -      unsigned int phy_no;
 -      int val;
 -
 -      if (hisi_hba->debugfs_bist_enable)
 -              return -EPERM;
 -
 -      val = kstrtouint_from_user(buf, count, 0, &phy_no);
 -      if (val)
 -              return val;
 -
 -      if (phy_no >= hisi_hba->n_phy)
 -              return -EINVAL;
 -
 -      hisi_hba->debugfs_bist_phy_no = phy_no;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_hba *hisi_hba = s->private;
 -
 -      seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_bist_phy_open(struct inode *inode,
 -                                        struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_bist_phy_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_bist_phy_ops = {
 -      .open = hisi_sas_debugfs_bist_phy_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_bist_phy_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static const struct {
 -      int             value;
 -      char            *name;
 -} hisi_sas_debugfs_loop_modes[] = {
 -      { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" },
 -      { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" },
 -      { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" },
 -};
 -
 -static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_hba *hisi_hba = s->private;
 -      int i;
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) {
 -              int match = (hisi_hba->debugfs_bist_mode ==
 -                           hisi_sas_debugfs_loop_modes[i].value);
 -
 -              seq_printf(s, "%s%s%s ", match ? "[" : "",
 -                         hisi_sas_debugfs_loop_modes[i].name,
 -                         match ? "]" : "");
 -      }
 -      seq_puts(s, "\n");
 -
 -      return 0;
 -}
 -
 -static ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp,
 -                                              const char __user *buf,
 -                                              size_t count, loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      struct hisi_hba *hisi_hba = m->private;
 -      char kbuf[16] = {}, *pkbuf;
 -      bool found = false;
 -      int i;
 -
 -      if (hisi_hba->debugfs_bist_enable)
 -              return -EPERM;
 -
 -      if (count >= sizeof(kbuf))
 -              return -EINVAL;
 -
 -      if (copy_from_user(kbuf, buf, count))
 -              return -EOVERFLOW;
 -
 -      pkbuf = strstrip(kbuf);
 -
 -      for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) {
 -              if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) {
 -                      hisi_hba->debugfs_bist_mode =
 -                              hisi_sas_debugfs_loop_modes[i].value;
 -                      found = true;
 -                      break;
 -              }
 -      }
 -
 -      if (!found)
 -              return -EINVAL;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_bist_mode_open(struct inode *inode,
 -                                         struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_bist_mode_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_bist_mode_ops = {
 -      .open = hisi_sas_debugfs_bist_mode_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_bist_mode_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp,
 -                                                const char __user *buf,
 -                                                size_t count, loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      struct hisi_hba *hisi_hba = m->private;
 -      unsigned int enable;
 -      int val;
 -
 -      val = kstrtouint_from_user(buf, count, 0, &enable);
 -      if (val)
 -              return val;
 -
 -      if (enable > 1)
 -              return -EINVAL;
 -
 -      if (enable == hisi_hba->debugfs_bist_enable)
 -              return count;
 -
 -      if (!hisi_hba->hw->set_bist)
 -              return -EPERM;
 -
 -      val = hisi_hba->hw->set_bist(hisi_hba, enable);
 -      if (val < 0)
 -              return val;
 -
 -      hisi_hba->debugfs_bist_enable = enable;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_hba *hisi_hba = s->private;
 -
 -      seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_bist_enable_open(struct inode *inode,
 -                                           struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_bist_enable_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_bist_enable_ops = {
 -      .open = hisi_sas_debugfs_bist_enable_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_bist_enable_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static const struct {
 -      char *name;
 -} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = {
 -      { "SAS_1_5_GBPS" },
 -      { "SAS_3_0_GBPS" },
 -      { "SAS_6_0_GBPS" },
 -      { "SAS_12_0_GBPS" },
 -      { "FFE_RESV" },
 -      { "SATA_1_5_GBPS" },
 -      { "SATA_3_0_GBPS" },
 -      { "SATA_6_0_GBPS" },
 -};
 -
 -static ssize_t hisi_sas_debugfs_write(struct file *filp,
 -                                    const char __user *buf,
 -                                    size_t count, loff_t *ppos)
 -{
 -      struct seq_file *m = filp->private_data;
 -      u32 *val = m->private;
 -      int res;
 -
 -      res = kstrtouint_from_user(buf, count, 0, val);
 -      if (res)
 -              return res;
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_show(struct seq_file *s, void *p)
 -{
 -      u32 *val = s->private;
 -
 -      seq_printf(s, "0x%x\n", *val);
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_ops = {
 -      .open = hisi_sas_debugfs_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
 -                                                 const char __user *buf,
 -                                                 size_t count, loff_t *ppos)
 -{
 -      struct seq_file *s = filp->private_data;
 -      struct hisi_sas_phy *phy = s->private;
 -      unsigned int set_val;
 -      int res;
 -
 -      res = kstrtouint_from_user(buf, count, 0, &set_val);
 -      if (res)
 -              return res;
 -
 -      if (set_val > 0)
 -              return -EINVAL;
 -
 -      atomic_set(&phy->down_cnt, 0);
 -
 -      return count;
 -}
 -
 -static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p)
 -{
 -      struct hisi_sas_phy *phy = s->private;
 -
 -      seq_printf(s, "%d\n", atomic_read(&phy->down_cnt));
 -
 -      return 0;
 -}
 -
 -static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode,
 -                                            struct file *filp)
 -{
 -      return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show,
 -                         inode->i_private);
 -}
 -
 -static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = {
 -      .open = hisi_sas_debugfs_phy_down_cnt_open,
 -      .read = seq_read,
 -      .write = hisi_sas_debugfs_phy_down_cnt_write,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -      .owner = THIS_MODULE,
 -};
 -
 -void hisi_sas_debugfs_work_handler(struct work_struct *work)
 -{
 -      struct hisi_hba *hisi_hba =
 -              container_of(work, struct hisi_hba, debugfs_work);
 -      int debugfs_dump_index = hisi_hba->debugfs_dump_index;
 -      struct device *dev = hisi_hba->dev;
 -      u64 timestamp = local_clock();
 -
 -      if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
 -              dev_warn(dev, "dump count exceeded!\n");
 -              return;
 -      }
 -
 -      do_div(timestamp, NSEC_PER_MSEC);
 -      hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
 -
 -      hisi_sas_debugfs_snapshot_regs(hisi_hba);
 -      hisi_hba->debugfs_dump_index++;
 -}
 -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler);
 -
 -static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index)
 -{
 -      struct device *dev = hisi_hba->dev;
 -      int i;
 -
 -      devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
 -      devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
 -      devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
 -      devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
 -
 -      for (i = 0; i < hisi_hba->queue_count; i++)
 -              devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
 -
 -      for (i = 0; i < hisi_hba->queue_count; i++)
 -              devm_kfree(dev,
 -                         hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
 -
 -      for (i = 0; i < DEBUGFS_REGS_NUM; i++)
 -              devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
 -
 -      for (i = 0; i < hisi_hba->n_phy; i++)
 -              devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
 -}
 -
 -static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index)
 -{
 -      const struct hisi_sas_hw *hw = hisi_hba->hw;
 -      struct device *dev = hisi_hba->dev;
 -      int p, c, d, r, i;
 -      size_t sz;
 -
 -      for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
 -              struct hisi_sas_debugfs_regs *regs =
 -                              &hisi_hba->debugfs_regs[dump_index][r];
 -
 -              sz = hw->debugfs_reg_array[r]->count * 4;
 -              regs->data = devm_kmalloc(dev, sz, GFP_KERNEL);
 -              if (!regs->data)
 -                      goto fail;
 -              regs->hisi_hba = hisi_hba;
 -      }
 -
 -      sz = hw->debugfs_reg_port->count * 4;
 -      for (p = 0; p < hisi_hba->n_phy; p++) {
 -              struct hisi_sas_debugfs_port *port =
 -                              &hisi_hba->debugfs_port_reg[dump_index][p];
 -
 -              port->data = devm_kmalloc(dev, sz, GFP_KERNEL);
 -              if (!port->data)
 -                      goto fail;
 -              port->phy = &hisi_hba->phy[p];
 -      }
 -
 -      sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
 -      for (c = 0; c < hisi_hba->queue_count; c++) {
 -              struct hisi_sas_debugfs_cq *cq =
 -                              &hisi_hba->debugfs_cq[dump_index][c];
 -
 -              cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
 -              if (!cq->complete_hdr)
 -                      goto fail;
 -              cq->cq = &hisi_hba->cq[c];
 -      }
 -
 -      sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
 -      for (d = 0; d < hisi_hba->queue_count; d++) {
 -              struct hisi_sas_debugfs_dq *dq =
 -                              &hisi_hba->debugfs_dq[dump_index][d];
 -
 -              dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
 -              if (!dq->hdr)
 -                      goto fail;
 -              dq->dq = &hisi_hba->dq[d];
 -      }
 -
 -      sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost);
 -
 -      hisi_hba->debugfs_iost[dump_index].iost =
 -                              devm_kmalloc(dev, sz, GFP_KERNEL);
 -      if (!hisi_hba->debugfs_iost[dump_index].iost)
 -              goto fail;
 -
 -      sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
 -           sizeof(struct hisi_sas_iost_itct_cache);
 -
 -      hisi_hba->debugfs_iost_cache[dump_index].cache =
 -                              devm_kmalloc(dev, sz, GFP_KERNEL);
 -      if (!hisi_hba->debugfs_iost_cache[dump_index].cache)
 -              goto fail;
 -
 -      sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
 -           sizeof(struct hisi_sas_iost_itct_cache);
 -
 -      hisi_hba->debugfs_itct_cache[dump_index].cache =
 -                              devm_kmalloc(dev, sz, GFP_KERNEL);
 -      if (!hisi_hba->debugfs_itct_cache[dump_index].cache)
 -              goto fail;
 -
 -      /* New memory allocation must be locate before itct */
 -      sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
 -
 -      hisi_hba->debugfs_itct[dump_index].itct =
 -                              devm_kmalloc(dev, sz, GFP_KERNEL);
 -      if (!hisi_hba->debugfs_itct[dump_index].itct)
 -              goto fail;
 -
 -      return 0;
 -fail:
 -      for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
 -              hisi_sas_debugfs_release(hisi_hba, i);
 -      return -ENOMEM;
 -}
 -
 -static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
 -{
 -      struct dentry *dir = debugfs_create_dir("phy_down_cnt",
 -                                              hisi_hba->debugfs_dir);
 -      char name[16];
 -      int phy_no;
 -
 -      for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
 -              snprintf(name, 16, "%d", phy_no);
 -              debugfs_create_file(name, 0600, dir,
 -                                  &hisi_hba->phy[phy_no],
 -                                  &hisi_sas_debugfs_phy_down_cnt_ops);
 -      }
 -}
 -
 -static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
 -{
 -      struct dentry *ports_dentry;
 -      int phy_no;
 -
 -      hisi_hba->debugfs_bist_dentry =
 -                      debugfs_create_dir("bist", hisi_hba->debugfs_dir);
 -      debugfs_create_file("link_rate", 0600,
 -                          hisi_hba->debugfs_bist_dentry, hisi_hba,
 -                          &hisi_sas_debugfs_bist_linkrate_ops);
 -
 -      debugfs_create_file("code_mode", 0600,
 -                          hisi_hba->debugfs_bist_dentry, hisi_hba,
 -                          &hisi_sas_debugfs_bist_code_mode_ops);
 -
 -      debugfs_create_file("fixed_code", 0600,
 -                          hisi_hba->debugfs_bist_dentry,
 -                          &hisi_hba->debugfs_bist_fixed_code[0],
 -                          &hisi_sas_debugfs_ops);
 -
 -      debugfs_create_file("fixed_code_1", 0600,
 -                          hisi_hba->debugfs_bist_dentry,
 -                          &hisi_hba->debugfs_bist_fixed_code[1],
 -                          &hisi_sas_debugfs_ops);
 -
 -      debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry,
 -                          hisi_hba, &hisi_sas_debugfs_bist_phy_ops);
 -
 -      debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry,
 -                         &hisi_hba->debugfs_bist_cnt);
 -
 -      debugfs_create_file("loopback_mode", 0600,
 -                          hisi_hba->debugfs_bist_dentry,
 -                          hisi_hba, &hisi_sas_debugfs_bist_mode_ops);
 -
 -      debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry,
 -                          hisi_hba, &hisi_sas_debugfs_bist_enable_ops);
 -
 -      ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry);
 -
 -      for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
 -              struct dentry *port_dentry;
 -              struct dentry *ffe_dentry;
 -              char name[256];
 -              int i;
 -
 -              snprintf(name, 256, "%d", phy_no);
 -              port_dentry = debugfs_create_dir(name, ports_dentry);
 -              ffe_dentry = debugfs_create_dir("ffe", port_dentry);
 -              for (i = 0; i < FFE_CFG_MAX; i++) {
 -                      if (i == FFE_RESV)
 -                              continue;
 -                      debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name,
 -                                          0600, ffe_dentry,
 -                                          &hisi_hba->debugfs_bist_ffe[phy_no][i],
 -                                          &hisi_sas_debugfs_ops);
 -              }
 -      }
 -
 -      hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
 -}
 -
 -void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
 -{
 -      struct device *dev = hisi_hba->dev;
 -      int i;
 -
 -      hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
 -                                                 hisi_sas_debugfs_dir);
 -      debugfs_create_file("trigger_dump", 0200,
 -                          hisi_hba->debugfs_dir,
 -                          hisi_hba,
 -                          &hisi_sas_debugfs_trigger_dump_fops);
 -
 -      /* create bist structures */
 -      hisi_sas_debugfs_bist_init(hisi_hba);
 -
 -      hisi_hba->debugfs_dump_dentry =
 -                      debugfs_create_dir("dump", hisi_hba->debugfs_dir);
 -
 -      hisi_sas_debugfs_phy_down_cnt_init(hisi_hba);
 -
 -      for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
 -              if (hisi_sas_debugfs_alloc(hisi_hba, i)) {
 -                      debugfs_remove_recursive(hisi_hba->debugfs_dir);
 -                      dev_dbg(dev, "failed to init debugfs!\n");
 -                      break;
 -              }
 -      }
 -}
 -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);
 -
 -void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba)
 -{
 -      debugfs_remove_recursive(hisi_hba->debugfs_dir);
 -}
 -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit);
 -
 -int hisi_sas_remove(struct platform_device *pdev)
 -{
 -      struct sas_ha_struct *sha = platform_get_drvdata(pdev);
 -      struct hisi_hba *hisi_hba = sha->lldd_ha;
 -      struct Scsi_Host *shost = sha->core.shost;
 -
 -      if (timer_pending(&hisi_hba->timer))
 -              del_timer(&hisi_hba->timer);
 -
 -      sas_unregister_ha(sha);
 -      sas_remove_host(sha->core.shost);
 -
 -      hisi_sas_free(hisi_hba);
 -      scsi_host_put(shost);
 -      return 0;
 -}
 -EXPORT_SYMBOL_GPL(hisi_sas_remove);
 -
 -bool hisi_sas_debugfs_enable;
 -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable);
 -module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
 -MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
 -
 -u32 hisi_sas_debugfs_dump_count = 1;
 -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count);
 -module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444);
 -MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
 +struct dentry *hisi_sas_debugfs_dir;
 +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dir);
  
  static __init int hisi_sas_init(void)
  {
index 6e4bf05c6d77f6b7bda8a121ca4282075a5b10ec,41cd66fc7d8122ef3f081f0d5c47e018a5a051d6..af192096a82b172ec188d83e2619f8da4216f21d
@@@ -37,6 -37,7 +37,7 @@@
  #include <linux/poll.h>
  #include <linux/vmalloc.h>
  #include <linux/irq_poll.h>
+ #include <linux/blk-mq-pci.h>
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
@@@ -113,6 -114,10 +114,10 @@@ unsigned int enable_sdev_max_qd
  module_param(enable_sdev_max_qd, int, 0444);
  MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue. Default: 0");
  
+ int host_tagset_enable = 1;
+ module_param(host_tagset_enable, int, 0444);
+ MODULE_PARM_DESC(host_tagset_enable, "Shared host tagset enable/disable Default: enable(1)");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(MEGASAS_VERSION);
  MODULE_AUTHOR("[email protected]");
@@@ -3119,6 -3124,19 +3124,19 @@@ megasas_bios_param(struct scsi_device *
        return 0;
  }
  
+ static int megasas_map_queues(struct Scsi_Host *shost)
+ {
+       struct megasas_instance *instance;
+       instance = (struct megasas_instance *)shost->hostdata;
+       if (shost->nr_hw_queues == 1)
+               return 0;
+       return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
+                       instance->pdev, instance->low_latency_index_start);
+ }
  static void megasas_aen_polling(struct work_struct *work);
  
  /**
@@@ -3427,6 -3445,7 +3445,7 @@@ static struct scsi_host_template megasa
        .eh_timed_out = megasas_reset_timer,
        .shost_attrs = megaraid_host_attrs,
        .bios_param = megasas_bios_param,
+       .map_queues = megasas_map_queues,
        .change_queue_depth = scsi_change_queue_depth,
        .max_segment_size = 0xffffffff,
  };
@@@ -6808,6 -6827,26 +6827,26 @@@ static int megasas_io_attach(struct meg
        host->max_lun = MEGASAS_MAX_LUN;
        host->max_cmd_len = 16;
  
+       /* Use shared host tagset only for fusion adaptors
+        * if there are managed interrupts (smp affinity enabled case).
+        * Single msix_vectors in kdump, so shared host tag is also disabled.
+        */
+       host->host_tagset = 0;
+       host->nr_hw_queues = 1;
+       if ((instance->adapter_type != MFI_SERIES) &&
+               (instance->msix_vectors > instance->low_latency_index_start) &&
+               host_tagset_enable &&
+               instance->smp_affinity_enable) {
+               host->host_tagset = 1;
+               host->nr_hw_queues = instance->msix_vectors -
+                       instance->low_latency_index_start;
+       }
+       dev_info(&instance->pdev->dev,
+               "Max firmware commands: %d shared with nr_hw_queues = %d\n",
+               instance->max_fw_cmds, host->nr_hw_queues);
        /*
         * Notify the mid-layer about the new controller
         */
@@@ -7554,23 -7593,25 +7593,23 @@@ static void megasas_shutdown_controller
        megasas_return_cmd(instance, cmd);
  }
  
 -#ifdef CONFIG_PM
  /**
   * megasas_suspend -  driver suspend entry point
 - * @pdev:             PCI device structure
 - * @state:            PCI power state to suspend routine
 + * @dev:              Device structure
   */
 -static int
 -megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 +static int __maybe_unused
 +megasas_suspend(struct device *dev)
  {
        struct megasas_instance *instance;
  
 -      instance = pci_get_drvdata(pdev);
 +      instance = dev_get_drvdata(dev);
  
        if (!instance)
                return 0;
  
        instance->unload = 1;
  
 -      dev_info(&pdev->dev, "%s is called\n", __func__);
 +      dev_info(dev, "%s is called\n", __func__);
  
        /* Shutdown SR-IOV heartbeat timer */
        if (instance->requestorId && !instance->skip_heartbeat_timer_del)
        if (instance->msix_vectors)
                pci_free_irq_vectors(instance->pdev);
  
 -      pci_save_state(pdev);
 -      pci_disable_device(pdev);
 -
 -      pci_set_power_state(pdev, pci_choose_state(pdev, state));
 -
        return 0;
  }
  
  /**
   * megasas_resume-      driver resume entry point
 - * @pdev:               PCI device structure
 + * @dev:              Device structure
   */
 -static int
 -megasas_resume(struct pci_dev *pdev)
 +static int __maybe_unused
 +megasas_resume(struct device *dev)
  {
        int rval;
        struct Scsi_Host *host;
        struct megasas_instance *instance;
        u32 status_reg;
  
 -      instance = pci_get_drvdata(pdev);
 +      instance = dev_get_drvdata(dev);
  
        if (!instance)
                return 0;
  
        host = instance->host;
 -      pci_set_power_state(pdev, PCI_D0);
 -      pci_enable_wake(pdev, PCI_D0, 0);
 -      pci_restore_state(pdev);
 -
 -      dev_info(&pdev->dev, "%s is called\n", __func__);
 -      /*
 -       * PCI prepping: enable device set bus mastering and dma mask
 -       */
 -      rval = pci_enable_device_mem(pdev);
  
 -      if (rval) {
 -              dev_err(&pdev->dev, "Enable device failed\n");
 -              return rval;
 -      }
 -
 -      pci_set_master(pdev);
 +      dev_info(dev, "%s is called\n", __func__);
  
        /*
         * We expect the FW state to be READY
@@@ -7748,8 -7808,14 +7787,8 @@@ fail_reenable_msix
  fail_set_dma_mask:
  fail_ready_state:
  
 -      pci_disable_device(pdev);
 -
        return -ENODEV;
  }
 -#else
 -#define megasas_suspend       NULL
 -#define megasas_resume        NULL
 -#endif
  
  static inline int
  megasas_wait_for_adapter_operational(struct megasas_instance *instance)
@@@ -7919,7 -7985,7 +7958,7 @@@ skip_firing_dcmds
  
  /**
   * megasas_shutdown - Shutdown entry point
 - * @pdev:             Generic device structure
 + * @pdev:             PCI device structure
   */
  static void megasas_shutdown(struct pci_dev *pdev)
  {
@@@ -8068,7 -8134,7 +8107,7 @@@ megasas_mgmt_fw_ioctl(struct megasas_in
        int error = 0, i;
        void *sense = NULL;
        dma_addr_t sense_handle;
 -      unsigned long *sense_ptr;
 +      void *sense_ptr;
        u32 opcode = 0;
        int ret = DCMD_SUCCESS;
  
        }
  
        if (ioc->sense_len) {
 +              /* make sure the pointer is part of the frame */
 +              if (ioc->sense_off >
 +                  (sizeof(union megasas_frame) - sizeof(__le64))) {
 +                      error = -EINVAL;
 +                      goto out;
 +              }
 +
                sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
                                             &sense_handle, GFP_KERNEL);
                if (!sense) {
                        goto out;
                }
  
 -              sense_ptr =
 -              (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
 +              sense_ptr = (void *)cmd->frame + ioc->sense_off;
                if (instance->consistent_mask_64bit)
 -                      *sense_ptr = cpu_to_le64(sense_handle);
 +                      put_unaligned_le64(sense_handle, sense_ptr);
                else
 -                      *sense_ptr = cpu_to_le32(sense_handle);
 +                      put_unaligned_le32(sense_handle, sense_ptr);
        }
  
        /*
         * copy out the sense
         */
        if (ioc->sense_len) {
 +              void __user *uptr;
                /*
                 * sense_ptr points to the location that has the user
                 * sense buffer address
                 */
 -              sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
 -                              ioc->sense_off);
 +              sense_ptr = (void *)ioc->frame.raw + ioc->sense_off;
 +              if (in_compat_syscall())
 +                      uptr = compat_ptr(get_unaligned((compat_uptr_t *)
 +                                                      sense_ptr));
 +              else
 +                      uptr = get_unaligned((void __user **)sense_ptr);
  
 -              if (copy_to_user((void __user *)((unsigned long)
 -                               get_unaligned((unsigned long *)sense_ptr)),
 -                               sense, ioc->sense_len)) {
 +              if (copy_to_user(uptr, sense, ioc->sense_len)) {
                        dev_err(&instance->pdev->dev, "Failed to copy out to user "
                                        "sense data\n");
                        error = -EFAULT;
        return error;
  }
  
 +static struct megasas_iocpacket *
 +megasas_compat_iocpacket_get_user(void __user *arg)
 +{
 +      struct megasas_iocpacket *ioc;
 +      struct compat_megasas_iocpacket __user *cioc = arg;
 +      size_t size;
 +      int err = -EFAULT;
 +      int i;
 +
 +      ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
 +      if (!ioc)
 +              return ERR_PTR(-ENOMEM);
 +      size = offsetof(struct megasas_iocpacket, frame) + sizeof(ioc->frame);
 +      if (copy_from_user(ioc, arg, size))
 +              goto out;
 +
 +      for (i = 0; i < MAX_IOCTL_SGE; i++) {
 +              compat_uptr_t iov_base;
 +
 +              if (get_user(iov_base, &cioc->sgl[i].iov_base) ||
 +                  get_user(ioc->sgl[i].iov_len, &cioc->sgl[i].iov_len))
 +                      goto out;
 +
 +              ioc->sgl[i].iov_base = compat_ptr(iov_base);
 +      }
 +
 +      return ioc;
 +out:
 +      kfree(ioc);
 +      return ERR_PTR(err);
 +}
 +
  static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
  {
        struct megasas_iocpacket __user *user_ioc =
        struct megasas_instance *instance;
        int error;
  
 -      ioc = memdup_user(user_ioc, sizeof(*ioc));
 +      if (in_compat_syscall())
 +              ioc = megasas_compat_iocpacket_get_user(user_ioc);
 +      else
 +              ioc = memdup_user(user_ioc, sizeof(struct megasas_iocpacket));
 +
        if (IS_ERR(ioc))
                return PTR_ERR(ioc);
  
@@@ -8457,13 -8478,78 +8496,13 @@@ megasas_mgmt_ioctl(struct file *file, u
  }
  
  #ifdef CONFIG_COMPAT
 -static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
 -{
 -      struct compat_megasas_iocpacket __user *cioc =
 -          (struct compat_megasas_iocpacket __user *)arg;
 -      struct megasas_iocpacket __user *ioc =
 -          compat_alloc_user_space(sizeof(struct megasas_iocpacket));
 -      int i;
 -      int error = 0;
 -      compat_uptr_t ptr;
 -      u32 local_sense_off;
 -      u32 local_sense_len;
 -      u32 user_sense_off;
 -
 -      if (clear_user(ioc, sizeof(*ioc)))
 -              return -EFAULT;
 -
 -      if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
 -          copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
 -          copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
 -          copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
 -          copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
 -          copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
 -              return -EFAULT;
 -
 -      /*
 -       * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
 -       * sense_len is not null, so prepare the 64bit value under
 -       * the same condition.
 -       */
 -      if (get_user(local_sense_off, &ioc->sense_off) ||
 -              get_user(local_sense_len, &ioc->sense_len) ||
 -              get_user(user_sense_off, &cioc->sense_off))
 -              return -EFAULT;
 -
 -      if (local_sense_off != user_sense_off)
 -              return -EINVAL;
 -
 -      if (local_sense_len) {
 -              void __user **sense_ioc_ptr =
 -                      (void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off);
 -              compat_uptr_t *sense_cioc_ptr =
 -                      (compat_uptr_t *)(((unsigned long)&cioc->frame.raw) + user_sense_off);
 -              if (get_user(ptr, sense_cioc_ptr) ||
 -                  put_user(compat_ptr(ptr), sense_ioc_ptr))
 -                      return -EFAULT;
 -      }
 -
 -      for (i = 0; i < MAX_IOCTL_SGE; i++) {
 -              if (get_user(ptr, &cioc->sgl[i].iov_base) ||
 -                  put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
 -                  copy_in_user(&ioc->sgl[i].iov_len,
 -                               &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
 -                      return -EFAULT;
 -      }
 -
 -      error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
 -
 -      if (copy_in_user(&cioc->frame.hdr.cmd_status,
 -                       &ioc->frame.hdr.cmd_status, sizeof(u8))) {
 -              printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
 -              return -EFAULT;
 -      }
 -      return error;
 -}
 -
  static long
  megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
                          unsigned long arg)
  {
        switch (cmd) {
        case MEGASAS_IOC_FIRMWARE32:
 -              return megasas_mgmt_compat_ioctl_fw(file, arg);
 +              return megasas_mgmt_ioctl_fw(file, arg);
        case MEGASAS_IOC_GET_AEN:
                return megasas_mgmt_ioctl_aen(file, arg);
        }
@@@ -8487,8 -8573,6 +8526,8 @@@ static const struct file_operations meg
        .llseek = noop_llseek,
  };
  
 +static SIMPLE_DEV_PM_OPS(megasas_pm_ops, megasas_suspend, megasas_resume);
 +
  /*
   * PCI hotplug support registration structure
   */
@@@ -8498,7 -8582,8 +8537,7 @@@ static struct pci_driver megasas_pci_dr
        .id_table = megasas_pci_table,
        .probe = megasas_probe_one,
        .remove = megasas_detach_one,
 -      .suspend = megasas_suspend,
 -      .resume = megasas_resume,
 +      .driver.pm = &megasas_pm_ops,
        .shutdown = megasas_shutdown,
  };
  
This page took 0.139978 seconds and 4 git commands to generate.