aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUma Krishnan <ukrishn@linux.vnet.ibm.com>2016-06-15 19:49:57 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-07-12 23:16:31 -0400
commit704c4b0ddc03fc8a6575086070a823d3ef6e5fc4 (patch)
tree411adc1c784f5689aba5c12d8e288c081e6516a7
parent96e1b660faa44c958d19ccf064b939a00bed6c90 (diff)
cxlflash: Shutdown notify support for CXL Flash cards
Some CXL Flash cards need notification of device shutdown in order to flush pending I/Os. A PCI notification hook for shutdown has been added where the driver notifies the card and returns. When the device is removed in the PCI remove path, notification code will wait for shutdown processing to complete. Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Acked-by: Manoj N. Kumar <manoj@linux.vnet.ibm.com> Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/cxlflash/main.c67
-rw-r--r--drivers/scsi/cxlflash/main.h1
-rw-r--r--drivers/scsi/cxlflash/sislite.h6
3 files changed, 73 insertions, 1 deletions
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index e027fa0fe430..860008d42466 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -765,6 +765,67 @@ static void term_afu(struct cxlflash_cfg *cfg)
765} 765}
766 766
767/** 767/**
768 * notify_shutdown() - notifies device of pending shutdown
769 * @cfg: Internal structure associated with the host.
770 * @wait: Whether to wait for shutdown processing to complete.
771 *
772 * This function will notify the AFU that the adapter is being shutdown
773 * and will wait for shutdown processing to complete if wait is true.
774 * This notification should flush pending I/Os to the device and halt
775 * further I/Os until the next AFU reset is issued and device restarted.
776 */
777static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
778{
779 struct afu *afu = cfg->afu;
780 struct device *dev = &cfg->dev->dev;
781 struct sisl_global_map __iomem *global = &afu->afu_map->global;
782 struct dev_dependent_vals *ddv;
783 u64 reg, status;
784 int i, retry_cnt = 0;
785
786 ddv = (struct dev_dependent_vals *)cfg->dev_id->driver_data;
787 if (!(ddv->flags & CXLFLASH_NOTIFY_SHUTDOWN))
788 return;
789
790 /* Notify AFU */
791 for (i = 0; i < NUM_FC_PORTS; i++) {
792 reg = readq_be(&global->fc_regs[i][FC_CONFIG2 / 8]);
793 reg |= SISL_FC_SHUTDOWN_NORMAL;
794 writeq_be(reg, &global->fc_regs[i][FC_CONFIG2 / 8]);
795 }
796
797 if (!wait)
798 return;
799
800 /* Wait up to 1.5 seconds for shutdown processing to complete */
801 for (i = 0; i < NUM_FC_PORTS; i++) {
802 retry_cnt = 0;
803 while (true) {
804 status = readq_be(&global->fc_regs[i][FC_STATUS / 8]);
805 if (status & SISL_STATUS_SHUTDOWN_COMPLETE)
806 break;
807 if (++retry_cnt >= MC_RETRY_CNT) {
808 dev_dbg(dev, "%s: port %d shutdown processing "
809 "not yet completed\n", __func__, i);
810 break;
811 }
812 msleep(100 * retry_cnt);
813 }
814 }
815}
816
817/**
818 * cxlflash_shutdown() - shutdown handler
819 * @pdev: PCI device associated with the host.
820 */
821static void cxlflash_shutdown(struct pci_dev *pdev)
822{
823 struct cxlflash_cfg *cfg = pci_get_drvdata(pdev);
824
825 notify_shutdown(cfg, false);
826}
827
828/**
768 * cxlflash_remove() - PCI entry point to tear down host 829 * cxlflash_remove() - PCI entry point to tear down host
769 * @pdev: PCI device associated with the host. 830 * @pdev: PCI device associated with the host.
770 * 831 *
@@ -785,6 +846,9 @@ static void cxlflash_remove(struct pci_dev *pdev)
785 cfg->tmf_slock); 846 cfg->tmf_slock);
786 spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); 847 spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
787 848
849 /* Notify AFU and wait for shutdown processing to complete */
850 notify_shutdown(cfg, true);
851
788 cfg->state = STATE_FAILTERM; 852 cfg->state = STATE_FAILTERM;
789 cxlflash_stop_term_user_contexts(cfg); 853 cxlflash_stop_term_user_contexts(cfg);
790 854
@@ -2336,7 +2400,7 @@ static struct scsi_host_template driver_template = {
2336static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS, 2400static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
2337 0ULL }; 2401 0ULL };
2338static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS, 2402static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
2339 0ULL }; 2403 CXLFLASH_NOTIFY_SHUTDOWN };
2340 2404
2341/* 2405/*
2342 * PCI device binding table 2406 * PCI device binding table
@@ -2613,6 +2677,7 @@ static struct pci_driver cxlflash_driver = {
2613 .id_table = cxlflash_pci_table, 2677 .id_table = cxlflash_pci_table,
2614 .probe = cxlflash_probe, 2678 .probe = cxlflash_probe,
2615 .remove = cxlflash_remove, 2679 .remove = cxlflash_remove,
2680 .shutdown = cxlflash_shutdown,
2616 .err_handler = &cxlflash_err_handler, 2681 .err_handler = &cxlflash_err_handler,
2617}; 2682};
2618 2683
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index 029f51743a24..f54bbd5a6062 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -89,6 +89,7 @@ enum undo_level {
89struct dev_dependent_vals { 89struct dev_dependent_vals {
90 u64 max_sectors; 90 u64 max_sectors;
91 u64 flags; 91 u64 flags;
92#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
92}; 93};
93 94
94struct asyc_intr_info { 95struct asyc_intr_info {
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index 0b3366f5e6f6..347fc1671975 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -311,6 +311,12 @@ struct sisl_global_regs {
311#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK) 311#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK)
312#define SISL_FC_INTERNAL_SHIFT 32 312#define SISL_FC_INTERNAL_SHIFT 32
313 313
314#define SISL_FC_SHUTDOWN_NORMAL 0x0000000000000010ULL
315#define SISL_FC_SHUTDOWN_ABRUPT 0x0000000000000020ULL
316
317#define SISL_STATUS_SHUTDOWN_ACTIVE 0x0000000000000010ULL
318#define SISL_STATUS_SHUTDOWN_COMPLETE 0x0000000000000020ULL
319
314#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */ 320#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */
315#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */ 321#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */
316 322