Skip to content

Commit 704c4b0

Browse files
umakrishnmartinkpetersen
authored andcommitted
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 <[email protected]> Acked-by: Manoj N. Kumar <[email protected]> Acked-by: Matthew R. Ochs <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 96e1b66 commit 704c4b0

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

drivers/scsi/cxlflash/main.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,67 @@ static void term_afu(struct cxlflash_cfg *cfg)
764764
pr_debug("%s: returning\n", __func__);
765765
}
766766

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+
*/
777+
static 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+
*/
821+
static 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+
767828
/**
768829
* cxlflash_remove() - PCI entry point to tear down host
769830
* @pdev: PCI device associated with the host.
@@ -785,6 +846,9 @@ static void cxlflash_remove(struct pci_dev *pdev)
785846
cfg->tmf_slock);
786847
spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
787848

849+
/* Notify AFU and wait for shutdown processing to complete */
850+
notify_shutdown(cfg, true);
851+
788852
cfg->state = STATE_FAILTERM;
789853
cxlflash_stop_term_user_contexts(cfg);
790854

@@ -2336,7 +2400,7 @@ static struct scsi_host_template driver_template = {
23362400
static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
23372401
0ULL };
23382402
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
2339-
0ULL };
2403+
CXLFLASH_NOTIFY_SHUTDOWN };
23402404

23412405
/*
23422406
* PCI device binding table
@@ -2613,6 +2677,7 @@ static struct pci_driver cxlflash_driver = {
26132677
.id_table = cxlflash_pci_table,
26142678
.probe = cxlflash_probe,
26152679
.remove = cxlflash_remove,
2680+
.shutdown = cxlflash_shutdown,
26162681
.err_handler = &cxlflash_err_handler,
26172682
};
26182683

drivers/scsi/cxlflash/main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ enum undo_level {
8989
struct dev_dependent_vals {
9090
u64 max_sectors;
9191
u64 flags;
92+
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
9293
};
9394

9495
struct asyc_intr_info {

drivers/scsi/cxlflash/sislite.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ struct sisl_global_regs {
311311
#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK)
312312
#define SISL_FC_INTERNAL_SHIFT 32
313313

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+
314320
#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */
315321
#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */
316322

0 commit comments

Comments
 (0)