From 0ae80ba91f57726f31b5b5890cb7c5173e624ca4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 12 Jun 2015 16:12:48 +0200 Subject: [PATCH 01/85] scsi: retry MODE SENSE on unit attention The 'sd' driver is calling scsi_mode_sense() to figure out internal details. But scsi_mode_sense() never checks for any pending unit attentions, so we're getting annoying error messages like: MODE SENSE: unimplemented page/subpage: 0x00/0x00 and a possible wrong decision for device cache handling. Reviewed-by: Ewan Milne Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 448ebdaa3d69..dffa91c67f5b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2423,7 +2423,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char cmd[12]; int use_10_for_ms; int header_length; - int result; + int result, retry_count = retries; struct scsi_sense_hdr my_sshdr; memset(data, 0, sizeof(*data)); @@ -2502,6 +2502,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->block_descriptor_length = buffer[3]; } data->header_length = header_length; + } else if ((status_byte(result) == CHECK_CONDITION) && + scsi_sense_valid(sshdr) && + sshdr->sense_key == UNIT_ATTENTION && retry_count) { + retry_count--; + goto retry; } return result; From bb8647e86e769bd45d2d5e010b3af516210d5760 Mon Sep 17 00:00:00 2001 From: Wen Xiong Date: Thu, 11 Jun 2015 20:45:18 -0500 Subject: [PATCH 02/85] ipr: Byte swapping for device_id attribute in sysfs On LE system, users see the wrong device_id attribute. This patch does necessary byte swapping for device_id attribute and works on both of LE and BE systems. Signed-off-by: Wen Xiong Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index a9aa38903efe..15da7544177c 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4455,7 +4455,7 @@ static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *a spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); res = (struct ipr_resource_entry *)sdev->hostdata; if (res && ioa_cfg->sis64) - len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id); + len = snprintf(buf, PAGE_SIZE, "0x%llx\n", be64_to_cpu(res->dev_id)); else if (res) len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn); From 359d96e73cea0ef2429db20e1a2322c75bc13830 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 11 Jun 2015 20:45:20 -0500 Subject: [PATCH 03/85] ipr: Endian / sparse fixes Some misc fixes for endianness checking with sparse so sparse with endian checking now runs clean. Fixes a minor bug in the process which was uncovered by sparse which would result in unnecessary error recovery for check conditions. Signed-off-by: Brian King Reviewed-by: Wen Xiong Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 13 +++++++------ drivers/scsi/ipr.h | 13 ++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 15da7544177c..341191952155 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1165,7 +1165,8 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, if (ioa_cfg->sis64) { proto = cfgtew->u.cfgte64->proto; - res->res_flags = cfgtew->u.cfgte64->res_flags; + res->flags = be16_to_cpu(cfgtew->u.cfgte64->flags); + res->res_flags = be16_to_cpu(cfgtew->u.cfgte64->res_flags); res->qmodel = IPR_QUEUEING_MODEL64(res); res->type = cfgtew->u.cfgte64->res_type; @@ -1313,8 +1314,8 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res, int new_path = 0; if (res->ioa_cfg->sis64) { - res->flags = cfgtew->u.cfgte64->flags; - res->res_flags = cfgtew->u.cfgte64->res_flags; + res->flags = be16_to_cpu(cfgtew->u.cfgte64->flags); + res->res_flags = be16_to_cpu(cfgtew->u.cfgte64->res_flags); res->type = cfgtew->u.cfgte64->res_type; memcpy(&res->std_inq_data, &cfgtew->u.cfgte64->std_inq_data, @@ -1900,7 +1901,7 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg, * Return value: * none **/ -static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len) +static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, __be32 *data, int len) { int i; @@ -2270,7 +2271,7 @@ static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, ((unsigned long)fabric + be16_to_cpu(fabric->length)); } - ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); + ipr_log_hex_data(ioa_cfg, (__be32 *)fabric, add_len); } /** @@ -2364,7 +2365,7 @@ static void ipr_log_sis64_fabric_error(struct ipr_ioa_cfg *ioa_cfg, ((unsigned long)fabric + be16_to_cpu(fabric->length)); } - ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); + ipr_log_hex_data(ioa_cfg, (__be32 *)fabric, add_len); } /** diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 6b97ee45c7b4..0cca05f0fc3d 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1005,13 +1005,13 @@ struct ipr_hostrcb_type_24_error { struct ipr_hostrcb_type_07_error { u8 failure_reason[64]; struct ipr_vpd vpd; - u32 data[222]; + __be32 data[222]; }__attribute__((packed, aligned (4))); struct ipr_hostrcb_type_17_error { u8 failure_reason[64]; struct ipr_ext_vpd vpd; - u32 data[476]; + __be32 data[476]; }__attribute__((packed, aligned (4))); struct ipr_hostrcb_config_element { @@ -1289,18 +1289,17 @@ struct ipr_resource_entry { (((res)->bus << 24) | ((res)->target << 8) | (res)->lun) u8 ata_class; - - u8 flags; - __be16 res_flags; - u8 type; + u16 flags; + u16 res_flags; + u8 qmodel; struct ipr_std_inq_data std_inq_data; __be32 res_handle; __be64 dev_id; - __be64 lun_wwn; + u64 lun_wwn; struct scsi_lun dev_lun; u8 res_path[8]; From aaf1b059387863ac9675eb42d01d03415c7529a5 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 11 Jun 2015 20:45:22 -0500 Subject: [PATCH 04/85] ipr: Driver version 2.6.2 Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 0cca05f0fc3d..e4fb17a58649 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -39,8 +39,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.6.1" -#define IPR_DRIVER_DATE "(March 12, 2015)" +#define IPR_DRIVER_VERSION "2.6.2" +#define IPR_DRIVER_DATE "(June 11, 2015)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding From 9c8108a4d3a837c51a29f28229a06d97654eaeb6 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 16 Jun 2015 16:07:13 -0700 Subject: [PATCH 05/85] iSCSI: let session recovery_tmo sysfs writes persist across recovery The iSCSI session recovery_tmo setting is writeable in sysfs, but it's also set every time a connection is established when parameters are set from iscsid over netlink. That results in the timeout being reset to the default value after every recovery. The DM multipath tools want to use the sysfs interface to lower the default timeout when there are multiple paths to fail over. It has caused confusion that we have a writeable sysfs value that seem to keep resetting itself. This patch adds an in-kernel flag that gets set once a sysfs write occurs, and then ignores netlink parameter setting once it's been modified via the sysfs interface. My thinking here is that the sysfs interface is much simpler for external tools to influence the session timeout, but if we're going to allow it to be modified directly we should ensure that setting is maintained. Signed-off-by: Chris Leech Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 11 ++++++++--- include/scsi/scsi_transport_iscsi.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 55647aae065c..4c25539abc84 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2042,6 +2042,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, session->transport = transport; session->creator = -1; session->recovery_tmo = 120; + session->recovery_tmo_sysfs_override = false; session->state = ISCSI_SESSION_FREE; INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->sess_list); @@ -2786,7 +2787,8 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) switch (ev->u.set_param.param) { case ISCSI_PARAM_SESS_RECOVERY_TMO: sscanf(data, "%d", &value); - session->recovery_tmo = value; + if (!session->recovery_tmo_sysfs_override) + session->recovery_tmo = value; break; default: err = transport->set_param(conn, ev->u.set_param.param, @@ -4049,13 +4051,15 @@ store_priv_session_##field(struct device *dev, \ if ((session->state == ISCSI_SESSION_FREE) || \ (session->state == ISCSI_SESSION_FAILED)) \ return -EBUSY; \ - if (strncmp(buf, "off", 3) == 0) \ + if (strncmp(buf, "off", 3) == 0) { \ session->field = -1; \ - else { \ + session->field##_sysfs_override = true; \ + } else { \ val = simple_strtoul(buf, &cp, 0); \ if (*cp != '\0' && *cp != '\n') \ return -EINVAL; \ session->field = val; \ + session->field##_sysfs_override = true; \ } \ return count; \ } @@ -4066,6 +4070,7 @@ store_priv_session_##field(struct device *dev, \ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \ show_priv_session_##field, \ store_priv_session_##field) + iscsi_priv_session_rw_attr(recovery_tmo, "%d"); static struct attribute *iscsi_session_attrs[] = { diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 2555ee5343fd..6183d20a01fb 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -241,6 +241,7 @@ struct iscsi_cls_session { /* recovery fields */ int recovery_tmo; + bool recovery_tmo_sysfs_override; struct delayed_work recovery_work; unsigned int target_id; From 2dc127bb299d1c7436a08e79193bd0251068356e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 4 Jun 2015 17:47:56 +0300 Subject: [PATCH 06/85] hpsa: fix an sprintf() overflow in the reset handler The string "cmd %d RESET FAILED, new lockup detected" is not quite large enough so the sprintf() will overflow. I have increased the size of the buffer and also changed the sprintf calls to snprintf. Fixes: 73153fe533bc ('hpsa: use block layer tag for command allocation') Signed-off-by: Dan Carpenter Acked-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1dafeb43333b..cab4e98b2b0e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -5104,7 +5104,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) int rc; struct ctlr_info *h; struct hpsa_scsi_dev_t *dev; - char msg[40]; + char msg[48]; /* find the controller to which the command to be aborted was sent */ h = sdev_to_hba(scsicmd->device); @@ -5122,16 +5122,18 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) /* if controller locked up, we can guarantee command won't complete */ if (lockup_detected(h)) { - sprintf(msg, "cmd %d RESET FAILED, lockup detected", - hpsa_get_cmd_index(scsicmd)); + snprintf(msg, sizeof(msg), + "cmd %d RESET FAILED, lockup detected", + hpsa_get_cmd_index(scsicmd)); hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); return FAILED; } /* this reset request might be the result of a lockup; check */ if (detect_controller_lockup(h)) { - sprintf(msg, "cmd %d RESET FAILED, new lockup detected", - hpsa_get_cmd_index(scsicmd)); + snprintf(msg, sizeof(msg), + "cmd %d RESET FAILED, new lockup detected", + hpsa_get_cmd_index(scsicmd)); hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); return FAILED; } @@ -5145,7 +5147,8 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) /* send a reset to the SCSI LUN which the command was sent to */ rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN, DEFAULT_REPLY_QUEUE); - sprintf(msg, "reset %s", rc == 0 ? "completed successfully" : "failed"); + snprintf(msg, sizeof(msg), "reset %s", + rc == 0 ? "completed successfully" : "failed"); hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); return rc == 0 ? SUCCESS : FAILED; } From c21e0bbfc48509a776ec4a39bd9a0fb45a9c315b Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Tue, 9 Jun 2015 17:15:52 -0500 Subject: [PATCH 07/85] cxlflash: Base support for IBM CXL Flash Adapter SCSI device driver to support filesystem access on the IBM CXL Flash adapter. Supported-by: Stephen Bates Reviewed-by: Michael Neuling Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reviewed-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + drivers/scsi/Makefile | 1 + drivers/scsi/cxlflash/Kconfig | 11 + drivers/scsi/cxlflash/Makefile | 2 + drivers/scsi/cxlflash/common.h | 180 +++ drivers/scsi/cxlflash/main.c | 2294 +++++++++++++++++++++++++++++++ drivers/scsi/cxlflash/main.h | 104 ++ drivers/scsi/cxlflash/sislite.h | 465 +++++++ 8 files changed, 3058 insertions(+) create mode 100644 drivers/scsi/cxlflash/Kconfig create mode 100644 drivers/scsi/cxlflash/Makefile create mode 100644 drivers/scsi/cxlflash/common.h create mode 100644 drivers/scsi/cxlflash/main.c create mode 100644 drivers/scsi/cxlflash/main.h create mode 100755 drivers/scsi/cxlflash/sislite.h diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 456e1567841c..95f7a76cfafc 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -345,6 +345,7 @@ source "drivers/scsi/cxgbi/Kconfig" source "drivers/scsi/bnx2i/Kconfig" source "drivers/scsi/bnx2fc/Kconfig" source "drivers/scsi/be2iscsi/Kconfig" +source "drivers/scsi/cxlflash/Kconfig" config SGIWD93_SCSI tristate "SGI WD93C93 SCSI Driver" diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 91209e3d27e3..471d08791766 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SCSI_7000FASST) += wd7000.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o +obj-$(CONFIG_CXLFLASH) += cxlflash/ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ obj-$(CONFIG_MEGARAID_SAS) += megaraid/ diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig new file mode 100644 index 000000000000..c7075084cfdb --- /dev/null +++ b/drivers/scsi/cxlflash/Kconfig @@ -0,0 +1,11 @@ +# +# IBM CXL-attached Flash Accelerator SCSI Driver +# + +config CXLFLASH + tristate "Support for IBM CAPI Flash" + depends on PCI && SCSI && CXL + default m + help + Allows CAPI Accelerated IO to Flash + If unsure, say N. diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile new file mode 100644 index 000000000000..dc95e203e3af --- /dev/null +++ b/drivers/scsi/cxlflash/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_CXLFLASH) += cxlflash.o +cxlflash-y += main.o diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h new file mode 100644 index 000000000000..5f43608dc8a1 --- /dev/null +++ b/drivers/scsi/cxlflash/common.h @@ -0,0 +1,180 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _CXLFLASH_COMMON_H +#define _CXLFLASH_COMMON_H + +#include +#include +#include +#include + + +#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */ + +#define CXLFLASH_BLOCK_SIZE 4096 /* 4K blocks */ +#define CXLFLASH_MAX_XFER_SIZE 16777216 /* 16MB transfer */ +#define CXLFLASH_MAX_SECTORS (CXLFLASH_MAX_XFER_SIZE/512) /* SCSI wants + max_sectors + in units of + 512 byte + sectors + */ + +#define NUM_RRQ_ENTRY 16 /* for master issued cmds */ +#define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry)) + +/* AFU command retry limit */ +#define MC_RETRY_CNT 5 /* sufficient for SCSI check and + certain AFU errors */ + +/* Command management definitions */ +#define CXLFLASH_NUM_CMDS (2 * CXLFLASH_MAX_CMDS) /* Must be a pow2 for + alignment and more + efficient array + index derivation + */ + +#define CXLFLASH_MAX_CMDS 16 +#define CXLFLASH_MAX_CMDS_PER_LUN CXLFLASH_MAX_CMDS + + +static inline void check_sizes(void) +{ + BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_NUM_CMDS); +} + +/* AFU defines a fixed size of 4K for command buffers (borrow 4K page define) */ +#define CMD_BUFSIZE SIZE_4K + +/* flags in IOA status area for host use */ +#define B_DONE 0x01 +#define B_ERROR 0x02 /* set with B_DONE */ +#define B_TIMEOUT 0x04 /* set with B_DONE & B_ERROR */ + +enum cxlflash_lr_state { + LINK_RESET_INVALID, + LINK_RESET_REQUIRED, + LINK_RESET_COMPLETE +}; + +enum cxlflash_init_state { + INIT_STATE_NONE, + INIT_STATE_PCI, + INIT_STATE_AFU, + INIT_STATE_SCSI +}; + +/* + * Each context has its own set of resource handles that is visible + * only from that context. + */ + +struct cxlflash_cfg { + struct afu *afu; + struct cxl_context *mcctx; + + struct pci_dev *dev; + struct pci_device_id *dev_id; + struct Scsi_Host *host; + + ulong cxlflash_regs_pci; + + wait_queue_head_t eeh_waitq; + + struct work_struct work_q; + enum cxlflash_init_state init_state; + enum cxlflash_lr_state lr_state; + int lr_port; + + struct cxl_afu *cxl_afu; + + struct pci_pool *cxlflash_cmd_pool; + struct pci_dev *parent_dev; + + wait_queue_head_t tmf_waitq; + bool tmf_active; + u8 err_recovery_active:1; +}; + +struct afu_cmd { + struct sisl_ioarcb rcb; /* IOARCB (cache line aligned) */ + struct sisl_ioasa sa; /* IOASA must follow IOARCB */ + spinlock_t slock; + struct completion cevent; + char *buf; /* per command buffer */ + struct afu *parent; + int slot; + atomic_t free; + + u8 cmd_tmf:1; + + /* As per the SISLITE spec the IOARCB EA has to be 16-byte aligned. + * However for performance reasons the IOARCB/IOASA should be + * cache line aligned. + */ +} __aligned(cache_line_size()); + +struct afu { + /* Stuff requiring alignment go first. */ + + u64 rrq_entry[NUM_RRQ_ENTRY]; /* 128B RRQ */ + /* + * Command & data for AFU commands. + */ + struct afu_cmd cmd[CXLFLASH_NUM_CMDS]; + + /* Beware of alignment till here. Preferably introduce new + * fields after this point + */ + + /* AFU HW */ + struct cxl_ioctl_start_work work; + struct cxlflash_afu_map *afu_map; /* entire MMIO map */ + struct sisl_host_map *host_map; /* MC host map */ + struct sisl_ctrl_map *ctrl_map; /* MC control map */ + + ctx_hndl_t ctx_hndl; /* master's context handle */ + u64 *hrrq_start; + u64 *hrrq_end; + u64 *hrrq_curr; + bool toggle; + bool read_room; + atomic64_t room; + u64 hb; + u32 cmd_couts; /* Number of command checkouts */ + u32 internal_lun; /* User-desired LUN mode for this AFU */ + + char version[8]; + u64 interface_version; + + struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */ + +}; + +static inline u64 lun_to_lunid(u64 lun) +{ + u64 lun_id; + + int_to_scsilun(lun, (struct scsi_lun *)&lun_id); + return swab64(lun_id); +} + +int cxlflash_send_cmd(struct afu *, struct afu_cmd *); +void cxlflash_wait_resp(struct afu *, struct afu_cmd *); +int cxlflash_afu_reset(struct cxlflash_cfg *); +struct afu_cmd *cxlflash_cmd_checkout(struct afu *); +void cxlflash_cmd_checkin(struct afu_cmd *); +int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8); +#endif /* ifndef _CXLFLASH_COMMON_H */ diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c new file mode 100644 index 000000000000..0720d2f13c2a --- /dev/null +++ b/drivers/scsi/cxlflash/main.c @@ -0,0 +1,2294 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include "main.h" +#include "sislite.h" +#include "common.h" + +MODULE_DESCRIPTION(CXLFLASH_ADAPTER_NAME); +MODULE_AUTHOR("Manoj N. Kumar "); +MODULE_AUTHOR("Matthew R. Ochs "); +MODULE_LICENSE("GPL"); + + +/** + * cxlflash_cmd_checkout() - checks out an AFU command + * @afu: AFU to checkout from. + * + * Commands are checked out in a round-robin fashion. Note that since + * the command pool is larger than the hardware queue, the majority of + * times we will only loop once or twice before getting a command. The + * buffer and CDB within the command are initialized (zeroed) prior to + * returning. + * + * Return: The checked out command or NULL when command pool is empty. + */ +struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu) +{ + int k, dec = CXLFLASH_NUM_CMDS; + struct afu_cmd *cmd; + + while (dec--) { + k = (afu->cmd_couts++ & (CXLFLASH_NUM_CMDS - 1)); + + cmd = &afu->cmd[k]; + + if (!atomic_dec_if_positive(&cmd->free)) { + pr_debug("%s: returning found index=%d\n", + __func__, cmd->slot); + memset(cmd->buf, 0, CMD_BUFSIZE); + memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb)); + return cmd; + } + } + + return NULL; +} + +/** + * cxlflash_cmd_checkin() - checks in an AFU command + * @cmd: AFU command to checkin. + * + * Safe to pass commands that have already been checked in. Several + * internal tracking fields are reset as part of the checkin. Note + * that these are intentionally reset prior to toggling the free bit + * to avoid clobbering values in the event that the command is checked + * out right away. + */ +void cxlflash_cmd_checkin(struct afu_cmd *cmd) +{ + cmd->rcb.scp = NULL; + cmd->rcb.timeout = 0; + cmd->sa.ioasc = 0; + cmd->cmd_tmf = false; + cmd->sa.host_use[0] = 0; /* clears both completion and retry bytes */ + + if (unlikely(atomic_inc_return(&cmd->free) != 1)) { + pr_err("%s: Freeing cmd (%d) that is not in use!\n", + __func__, cmd->slot); + return; + } + + pr_debug("%s: released cmd %p index=%d\n", __func__, cmd, cmd->slot); +} + +/** + * process_cmd_err() - command error handler + * @cmd: AFU command that experienced the error. + * @scp: SCSI command associated with the AFU command in error. + * + * Translates error bits from AFU command to SCSI command results. + */ +static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp) +{ + struct sisl_ioarcb *ioarcb; + struct sisl_ioasa *ioasa; + + if (unlikely(!cmd)) + return; + + ioarcb = &(cmd->rcb); + ioasa = &(cmd->sa); + + if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) { + pr_debug("%s: cmd underrun cmd = %p scp = %p\n", + __func__, cmd, scp); + scp->result = (DID_ERROR << 16); + } + + if (ioasa->rc.flags & SISL_RC_FLAGS_OVERRUN) { + pr_debug("%s: cmd underrun cmd = %p scp = %p\n", + __func__, cmd, scp); + scp->result = (DID_ERROR << 16); + } + + pr_debug("%s: cmd failed afu_rc=%d scsi_rc=%d fc_rc=%d " + "afu_extra=0x%X, scsi_entra=0x%X, fc_extra=0x%X\n", + __func__, ioasa->rc.afu_rc, ioasa->rc.scsi_rc, + ioasa->rc.fc_rc, ioasa->afu_extra, ioasa->scsi_extra, + ioasa->fc_extra); + + if (ioasa->rc.scsi_rc) { + /* We have a SCSI status */ + if (ioasa->rc.flags & SISL_RC_FLAGS_SENSE_VALID) { + memcpy(scp->sense_buffer, ioasa->sense_data, + SISL_SENSE_DATA_LEN); + scp->result = ioasa->rc.scsi_rc; + } else + scp->result = ioasa->rc.scsi_rc | (DID_ERROR << 16); + } + + /* + * We encountered an error. Set scp->result based on nature + * of error. + */ + if (ioasa->rc.fc_rc) { + /* We have an FC status */ + switch (ioasa->rc.fc_rc) { + case SISL_FC_RC_LINKDOWN: + scp->result = (DID_REQUEUE << 16); + break; + case SISL_FC_RC_RESID: + /* This indicates an FCP resid underrun */ + if (!(ioasa->rc.flags & SISL_RC_FLAGS_OVERRUN)) { + /* If the SISL_RC_FLAGS_OVERRUN flag was set, + * then we will handle this error else where. + * If not then we must handle it here. + * This is probably an AFU bug. We will + * attempt a retry to see if that resolves it. + */ + scp->result = (DID_ERROR << 16); + } + break; + case SISL_FC_RC_RESIDERR: + /* Resid mismatch between adapter and device */ + case SISL_FC_RC_TGTABORT: + case SISL_FC_RC_ABORTOK: + case SISL_FC_RC_ABORTFAIL: + case SISL_FC_RC_NOLOGI: + case SISL_FC_RC_ABORTPEND: + case SISL_FC_RC_WRABORTPEND: + case SISL_FC_RC_NOEXP: + case SISL_FC_RC_INUSE: + scp->result = (DID_ERROR << 16); + break; + } + } + + if (ioasa->rc.afu_rc) { + /* We have an AFU error */ + switch (ioasa->rc.afu_rc) { + case SISL_AFU_RC_NO_CHANNELS: + scp->result = (DID_MEDIUM_ERROR << 16); + break; + case SISL_AFU_RC_DATA_DMA_ERR: + switch (ioasa->afu_extra) { + case SISL_AFU_DMA_ERR_PAGE_IN: + /* Retry */ + scp->result = (DID_IMM_RETRY << 16); + break; + case SISL_AFU_DMA_ERR_INVALID_EA: + default: + scp->result = (DID_ERROR << 16); + } + break; + case SISL_AFU_RC_OUT_OF_DATA_BUFS: + /* Retry */ + scp->result = (DID_ALLOC_FAILURE << 16); + break; + default: + scp->result = (DID_ERROR << 16); + } + } +} + +/** + * cmd_complete() - command completion handler + * @cmd: AFU command that has completed. + * + * Prepares and submits command that has either completed or timed out to + * the SCSI stack. Checks AFU command back into command pool for non-internal + * (rcb.scp populated) commands. + */ +static void cmd_complete(struct afu_cmd *cmd) +{ + struct scsi_cmnd *scp; + u32 resid; + ulong lock_flags; + struct afu *afu = cmd->parent; + struct cxlflash_cfg *cfg = afu->parent; + bool cmd_is_tmf; + + spin_lock_irqsave(&cmd->slock, lock_flags); + cmd->sa.host_use_b[0] |= B_DONE; + spin_unlock_irqrestore(&cmd->slock, lock_flags); + + if (cmd->rcb.scp) { + scp = cmd->rcb.scp; + if (unlikely(cmd->sa.rc.afu_rc || + cmd->sa.rc.scsi_rc || + cmd->sa.rc.fc_rc)) + process_cmd_err(cmd, scp); + else + scp->result = (DID_OK << 16); + + resid = cmd->sa.resid; + cmd_is_tmf = cmd->cmd_tmf; + cxlflash_cmd_checkin(cmd); /* Don't use cmd after here */ + + pr_debug("%s: calling scsi_set_resid, scp=%p " + "result=%X resid=%d\n", __func__, + scp, scp->result, resid); + + scsi_set_resid(scp, resid); + scsi_dma_unmap(scp); + scp->scsi_done(scp); + + if (cmd_is_tmf) { + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + cfg->tmf_active = false; + wake_up_all_locked(&cfg->tmf_waitq); + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, + lock_flags); + } + } else + complete(&cmd->cevent); +} + +/** + * send_tmf() - sends a Task Management Function (TMF) + * @afu: AFU to checkout from. + * @scp: SCSI command from stack. + * @tmfcmd: TMF command to send. + * + * Return: + * 0 on success + * SCSI_MLQUEUE_HOST_BUSY when host is busy + */ +static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) +{ + struct afu_cmd *cmd; + + u32 port_sel = scp->device->channel + 1; + short lflag = 0; + struct Scsi_Host *host = scp->device->host; + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; + ulong lock_flags; + int rc = 0; + + cmd = cxlflash_cmd_checkout(afu); + if (unlikely(!cmd)) { + pr_err("%s: could not get a free command\n", __func__); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + + /* If a Task Management Function is active, do not send one more. + */ + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + if (cfg->tmf_active) + wait_event_interruptible_locked_irq(cfg->tmf_waitq, + !cfg->tmf_active); + cfg->tmf_active = true; + cmd->cmd_tmf = true; + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + + cmd->rcb.ctx_id = afu->ctx_hndl; + cmd->rcb.port_sel = port_sel; + cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); + + lflag = SISL_REQ_FLAGS_TMF_CMD; + + cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID | + SISL_REQ_FLAGS_SUP_UNDERRUN | lflag); + + /* Stash the scp in the reserved field, for reuse during interrupt */ + cmd->rcb.scp = scp; + + /* Copy the CDB from the cmd passed in */ + memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd)); + + /* Send the command */ + rc = cxlflash_send_cmd(afu, cmd); + if (unlikely(rc)) { + cxlflash_cmd_checkin(cmd); + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + cfg->tmf_active = false; + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + goto out; + } + + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + wait_event_interruptible_locked_irq(cfg->tmf_waitq, !cfg->tmf_active); + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); +out: + return rc; +} + +/** + * cxlflash_driver_info() - information handler for this host driver + * @host: SCSI host associated with device. + * + * Return: A string describing the device. + */ +static const char *cxlflash_driver_info(struct Scsi_Host *host) +{ + return CXLFLASH_ADAPTER_NAME; +} + +/** + * cxlflash_queuecommand() - sends a mid-layer request + * @host: SCSI host associated with device. + * @scp: SCSI command to send. + * + * Return: + * 0 on success + * SCSI_MLQUEUE_HOST_BUSY when host is busy + */ +static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; + struct afu *afu = cfg->afu; + struct pci_dev *pdev = cfg->dev; + struct afu_cmd *cmd; + u32 port_sel = scp->device->channel + 1; + int nseg, i, ncount; + struct scatterlist *sg; + ulong lock_flags; + short lflag = 0; + int rc = 0; + + pr_debug("%s: (scp=%p) %d/%d/%d/%llu cdb=(%08X-%08X-%08X-%08X)\n", + __func__, scp, host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + get_unaligned_be32(&((u32 *)scp->cmnd)[0]), + get_unaligned_be32(&((u32 *)scp->cmnd)[1]), + get_unaligned_be32(&((u32 *)scp->cmnd)[2]), + get_unaligned_be32(&((u32 *)scp->cmnd)[3])); + + /* If a Task Management Function is active, wait for it to complete + * before continuing with regular commands. + */ + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + if (cfg->tmf_active) { + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + + cmd = cxlflash_cmd_checkout(afu); + if (unlikely(!cmd)) { + pr_err("%s: could not get a free command\n", __func__); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + + cmd->rcb.ctx_id = afu->ctx_hndl; + cmd->rcb.port_sel = port_sel; + cmd->rcb.lun_id = lun_to_lunid(scp->device->lun); + + if (scp->sc_data_direction == DMA_TO_DEVICE) + lflag = SISL_REQ_FLAGS_HOST_WRITE; + else + lflag = SISL_REQ_FLAGS_HOST_READ; + + cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID | + SISL_REQ_FLAGS_SUP_UNDERRUN | lflag); + + /* Stash the scp in the reserved field, for reuse during interrupt */ + cmd->rcb.scp = scp; + + nseg = scsi_dma_map(scp); + if (unlikely(nseg < 0)) { + dev_err(&pdev->dev, "%s: Fail DMA map! nseg=%d\n", + __func__, nseg); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + + ncount = scsi_sg_count(scp); + scsi_for_each_sg(scp, sg, ncount, i) { + cmd->rcb.data_len = sg_dma_len(sg); + cmd->rcb.data_ea = sg_dma_address(sg); + } + + /* Copy the CDB from the scsi_cmnd passed in */ + memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb)); + + /* Send the command */ + rc = cxlflash_send_cmd(afu, cmd); + if (unlikely(rc)) { + cxlflash_cmd_checkin(cmd); + scsi_dma_unmap(scp); + } + +out: + return rc; +} + +/** + * cxlflash_eh_device_reset_handler() - reset a single LUN + * @scp: SCSI command to send. + * + * Return: + * SUCCESS as defined in scsi/scsi.h + * FAILED as defined in scsi/scsi.h + */ +static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp) +{ + int rc = SUCCESS; + struct Scsi_Host *host = scp->device->host; + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; + struct afu *afu = cfg->afu; + int rcr = 0; + + pr_debug("%s: (scp=%p) %d/%d/%d/%llu " + "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp, + host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + get_unaligned_be32(&((u32 *)scp->cmnd)[0]), + get_unaligned_be32(&((u32 *)scp->cmnd)[1]), + get_unaligned_be32(&((u32 *)scp->cmnd)[2]), + get_unaligned_be32(&((u32 *)scp->cmnd)[3])); + + rcr = send_tmf(afu, scp, TMF_LUN_RESET); + if (unlikely(rcr)) + rc = FAILED; + + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_eh_host_reset_handler() - reset the host adapter + * @scp: SCSI command from stack identifying host. + * + * Return: + * SUCCESS as defined in scsi/scsi.h + * FAILED as defined in scsi/scsi.h + */ +static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) +{ + int rc = SUCCESS; + int rcr = 0; + struct Scsi_Host *host = scp->device->host; + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; + + pr_debug("%s: (scp=%p) %d/%d/%d/%llu " + "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp, + host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + get_unaligned_be32(&((u32 *)scp->cmnd)[0]), + get_unaligned_be32(&((u32 *)scp->cmnd)[1]), + get_unaligned_be32(&((u32 *)scp->cmnd)[2]), + get_unaligned_be32(&((u32 *)scp->cmnd)[3])); + + rcr = cxlflash_afu_reset(cfg); + if (rcr == 0) + rc = SUCCESS; + else + rc = FAILED; + + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_change_queue_depth() - change the queue depth for the device + * @sdev: SCSI device destined for queue depth change. + * @qdepth: Requested queue depth value to set. + * + * The requested queue depth is capped to the maximum supported value. + * + * Return: The actual queue depth set. + */ +static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth) +{ + + if (qdepth > CXLFLASH_MAX_CMDS_PER_LUN) + qdepth = CXLFLASH_MAX_CMDS_PER_LUN; + + scsi_change_queue_depth(sdev, qdepth); + return sdev->queue_depth; +} + +/** + * cxlflash_show_port_status() - queries and presents the current port status + * @dev: Generic device associated with the host owning the port. + * @attr: Device attribute representing the port. + * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII. + * + * Return: The size of the ASCII string returned in @buf. + */ +static ssize_t cxlflash_show_port_status(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; + struct afu *afu = cfg->afu; + + char *disp_status; + int rc; + u32 port; + u64 status; + u64 *fc_regs; + + rc = kstrtouint((attr->attr.name + 4), 10, &port); + if (rc || (port > NUM_FC_PORTS)) + return 0; + + fc_regs = &afu->afu_map->global.fc_regs[port][0]; + status = + (readq_be(&fc_regs[FC_MTIP_STATUS / 8]) & FC_MTIP_STATUS_MASK); + + if (status == FC_MTIP_STATUS_ONLINE) + disp_status = "online"; + else if (status == FC_MTIP_STATUS_OFFLINE) + disp_status = "offline"; + else + disp_status = "unknown"; + + return snprintf(buf, PAGE_SIZE, "%s\n", disp_status); +} + +/** + * cxlflash_show_lun_mode() - presents the current LUN mode of the host + * @dev: Generic device associated with the host. + * @attr: Device attribute representing the lun mode. + * @buf: Buffer of length PAGE_SIZE to report back the LUN mode in ASCII. + * + * Return: The size of the ASCII string returned in @buf. + */ +static ssize_t cxlflash_show_lun_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; + struct afu *afu = cfg->afu; + + return snprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun); +} + +/** + * cxlflash_store_lun_mode() - sets the LUN mode of the host + * @dev: Generic device associated with the host. + * @attr: Device attribute representing the lun mode. + * @buf: Buffer of length PAGE_SIZE containing the LUN mode in ASCII. + * @count: Length of data resizing in @buf. + * + * The CXL Flash AFU supports a dummy LUN mode where the external + * links and storage are not required. Space on the FPGA is used + * to create 1 or 2 small LUNs which are presented to the system + * as if they were a normal storage device. This feature is useful + * during development and also provides manufacturing with a way + * to test the AFU without an actual device. + * + * 0 = external LUN[s] (default) + * 1 = internal LUN (1 x 64K, 512B blocks, id 0) + * 2 = internal LUN (1 x 64K, 4K blocks, id 0) + * 3 = internal LUN (2 x 32K, 512B blocks, ids 0,1) + * 4 = internal LUN (2 x 32K, 4K blocks, ids 0,1) + * + * Return: The size of the ASCII string returned in @buf. + */ +static ssize_t cxlflash_store_lun_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; + struct afu *afu = cfg->afu; + int rc; + u32 lun_mode; + + rc = kstrtouint(buf, 10, &lun_mode); + if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) { + afu->internal_lun = lun_mode; + cxlflash_afu_reset(cfg); + scsi_scan_host(cfg->host); + } + + return count; +} + +/** + * cxlflash_show_dev_mode() - presents the current mode of the device + * @dev: Generic device associated with the device. + * @attr: Device attribute representing the device mode. + * @buf: Buffer of length PAGE_SIZE to report back the dev mode in ASCII. + * + * Return: The size of the ASCII string returned in @buf. + */ +static ssize_t cxlflash_show_dev_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", + sdev->hostdata ? "superpipe" : "legacy"); +} + +/** + * cxlflash_wait_for_pci_err_recovery() - wait for error recovery during probe + * @cxlflash: Internal structure associated with the host. + */ +static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg) +{ + struct pci_dev *pdev = cfg->dev; + + if (pci_channel_offline(pdev)) + wait_event_timeout(cfg->eeh_waitq, + !pci_channel_offline(pdev), + CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT); +} + +/* + * Host attributes + */ +static DEVICE_ATTR(port0, S_IRUGO, cxlflash_show_port_status, NULL); +static DEVICE_ATTR(port1, S_IRUGO, cxlflash_show_port_status, NULL); +static DEVICE_ATTR(lun_mode, S_IRUGO | S_IWUSR, cxlflash_show_lun_mode, + cxlflash_store_lun_mode); + +static struct device_attribute *cxlflash_host_attrs[] = { + &dev_attr_port0, + &dev_attr_port1, + &dev_attr_lun_mode, + NULL +}; + +/* + * Device attributes + */ +static DEVICE_ATTR(mode, S_IRUGO, cxlflash_show_dev_mode, NULL); + +static struct device_attribute *cxlflash_dev_attrs[] = { + &dev_attr_mode, + NULL +}; + +/* + * Host template + */ +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = CXLFLASH_ADAPTER_NAME, + .info = cxlflash_driver_info, + .proc_name = CXLFLASH_NAME, + .queuecommand = cxlflash_queuecommand, + .eh_device_reset_handler = cxlflash_eh_device_reset_handler, + .eh_host_reset_handler = cxlflash_eh_host_reset_handler, + .change_queue_depth = cxlflash_change_queue_depth, + .cmd_per_lun = 16, + .can_queue = CXLFLASH_MAX_CMDS, + .this_id = -1, + .sg_tablesize = SG_NONE, /* No scatter gather support. */ + .max_sectors = CXLFLASH_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = cxlflash_host_attrs, + .sdev_attrs = cxlflash_dev_attrs, +}; + +/* + * Device dependent values + */ +static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS }; + +/* + * PCI device binding table + */ +static struct pci_device_id cxlflash_pci_table[] = { + {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals}, + {} +}; + +MODULE_DEVICE_TABLE(pci, cxlflash_pci_table); + +/** + * free_mem() - free memory associated with the AFU + * @cxlflash: Internal structure associated with the host. + */ +static void free_mem(struct cxlflash_cfg *cfg) +{ + int i; + char *buf = NULL; + struct afu *afu = cfg->afu; + + if (cfg->afu) { + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { + buf = afu->cmd[i].buf; + if (!((u64)buf & (PAGE_SIZE - 1))) + free_page((ulong)buf); + } + + free_pages((ulong)afu, get_order(sizeof(struct afu))); + cfg->afu = NULL; + } +} + +/** + * stop_afu() - stops the AFU command timers and unmaps the MMIO space + * @cxlflash: Internal structure associated with the host. + * + * Safe to call with AFU in a partially allocated/initialized state. + */ +static void stop_afu(struct cxlflash_cfg *cfg) +{ + int i; + struct afu *afu = cfg->afu; + + if (likely(afu)) { + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) + complete(&afu->cmd[i].cevent); + + if (likely(afu->afu_map)) { + cxl_psa_unmap((void *)afu->afu_map); + afu->afu_map = NULL; + } + } +} + +/** + * term_mc() - terminates the master context + * @cxlflash: Internal structure associated with the host. + * @level: Depth of allocation, where to begin waterfall tear down. + * + * Safe to call with AFU/MC in partially allocated/initialized state. + */ +static void term_mc(struct cxlflash_cfg *cfg, enum undo_level level) +{ + int rc = 0; + struct afu *afu = cfg->afu; + + if (!afu || !cfg->mcctx) { + pr_err("%s: returning from term_mc with NULL afu or MC\n", + __func__); + return; + } + + switch (level) { + case UNDO_START: + rc = cxl_stop_context(cfg->mcctx); + BUG_ON(rc); + case UNMAP_THREE: + cxl_unmap_afu_irq(cfg->mcctx, 3, afu); + case UNMAP_TWO: + cxl_unmap_afu_irq(cfg->mcctx, 2, afu); + case UNMAP_ONE: + cxl_unmap_afu_irq(cfg->mcctx, 1, afu); + case FREE_IRQ: + cxl_free_afu_irqs(cfg->mcctx); + case RELEASE_CONTEXT: + cfg->mcctx = NULL; + } +} + +/** + * term_afu() - terminates the AFU + * @cxlflash: Internal structure associated with the host. + * + * Safe to call with AFU/MC in partially allocated/initialized state. + */ +static void term_afu(struct cxlflash_cfg *cfg) +{ + term_mc(cfg, UNDO_START); + + if (cfg->afu) + stop_afu(cfg); + + pr_debug("%s: returning\n", __func__); +} + +/** + * cxlflash_remove() - PCI entry point to tear down host + * @pdev: PCI device associated with the host. + * + * Safe to use as a cleanup in partially allocated/initialized state. + */ +static void cxlflash_remove(struct pci_dev *pdev) +{ + struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); + ulong lock_flags; + + /* If a Task Management Function is active, wait for it to complete + * before continuing with remove. + */ + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags); + if (cfg->tmf_active) + wait_event_interruptible_locked_irq(cfg->tmf_waitq, + !cfg->tmf_active); + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + + switch (cfg->init_state) { + case INIT_STATE_SCSI: + scsi_remove_host(cfg->host); + scsi_host_put(cfg->host); + /* Fall through */ + case INIT_STATE_AFU: + term_afu(cfg); + case INIT_STATE_PCI: + pci_release_regions(cfg->dev); + pci_disable_device(pdev); + case INIT_STATE_NONE: + flush_work(&cfg->work_q); + free_mem(cfg); + break; + } + + pr_debug("%s: returning\n", __func__); +} + +/** + * alloc_mem() - allocates the AFU and its command pool + * @cxlflash: Internal structure associated with the host. + * + * A partially allocated state remains on failure. + * + * Return: + * 0 on success + * -ENOMEM on failure to allocate memory + */ +static int alloc_mem(struct cxlflash_cfg *cfg) +{ + int rc = 0; + int i; + char *buf = NULL; + + /* This allocation is about 12K, i.e. only 1 64k page + * and upto 4 4k pages + */ + cfg->afu = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(sizeof(struct afu))); + if (unlikely(!cfg->afu)) { + pr_err("%s: cannot get %d free pages\n", + __func__, get_order(sizeof(struct afu))); + rc = -ENOMEM; + goto out; + } + cfg->afu->parent = cfg; + cfg->afu->afu_map = NULL; + + for (i = 0; i < CXLFLASH_NUM_CMDS; buf += CMD_BUFSIZE, i++) { + if (!((u64)buf & (PAGE_SIZE - 1))) { + buf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + if (unlikely(!buf)) { + pr_err("%s: Allocate command buffers fail!\n", + __func__); + rc = -ENOMEM; + free_mem(cfg); + goto out; + } + } + + cfg->afu->cmd[i].buf = buf; + atomic_set(&cfg->afu->cmd[i].free, 1); + cfg->afu->cmd[i].slot = i; + } + +out: + return rc; +} + +/** + * init_pci() - initializes the host as a PCI device + * @cxlflash: Internal structure associated with the host. + * + * Return: + * 0 on success + * -EIO on unable to communicate with device + * A return code from the PCI sub-routines + */ +static int init_pci(struct cxlflash_cfg *cfg) +{ + struct pci_dev *pdev = cfg->dev; + int rc = 0; + + cfg->cxlflash_regs_pci = pci_resource_start(pdev, 0); + rc = pci_request_regions(pdev, CXLFLASH_NAME); + if (rc < 0) { + dev_err(&pdev->dev, + "%s: Couldn't register memory range of registers\n", + __func__); + goto out; + } + + rc = pci_enable_device(pdev); + if (rc || pci_channel_offline(pdev)) { + if (pci_channel_offline(pdev)) { + cxlflash_wait_for_pci_err_recovery(cfg); + rc = pci_enable_device(pdev); + } + + if (rc) { + dev_err(&pdev->dev, "%s: Cannot enable adapter\n", + __func__); + cxlflash_wait_for_pci_err_recovery(cfg); + goto out_release_regions; + } + } + + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (rc < 0) { + dev_dbg(&pdev->dev, "%s: Failed to set 64 bit PCI DMA mask\n", + __func__); + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + } + + if (rc < 0) { + dev_err(&pdev->dev, "%s: Failed to set PCI DMA mask\n", + __func__); + goto out_disable; + } + + pci_set_master(pdev); + + if (pci_channel_offline(pdev)) { + cxlflash_wait_for_pci_err_recovery(cfg); + if (pci_channel_offline(pdev)) { + rc = -EIO; + goto out_msi_disable; + } + } + + rc = pci_save_state(pdev); + + if (rc != PCIBIOS_SUCCESSFUL) { + dev_err(&pdev->dev, "%s: Failed to save PCI config space\n", + __func__); + rc = -EIO; + goto cleanup_nolog; + } + +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; + +cleanup_nolog: +out_msi_disable: + cxlflash_wait_for_pci_err_recovery(cfg); +out_disable: + pci_disable_device(pdev); +out_release_regions: + pci_release_regions(pdev); + goto out; + +} + +/** + * init_scsi() - adds the host to the SCSI stack and kicks off host scan + * @cxlflash: Internal structure associated with the host. + * + * Return: + * 0 on success + * A return code from adding the host + */ +static int init_scsi(struct cxlflash_cfg *cfg) +{ + struct pci_dev *pdev = cfg->dev; + int rc = 0; + + rc = scsi_add_host(cfg->host, &pdev->dev); + if (rc) { + dev_err(&pdev->dev, "%s: scsi_add_host failed (rc=%d)\n", + __func__, rc); + goto out; + } + + scsi_scan_host(cfg->host); + +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * set_port_online() - transitions the specified host FC port to online state + * @fc_regs: Top of MMIO region defined for specified port. + * + * The provided MMIO region must be mapped prior to call. Online state means + * that the FC link layer has synced, completed the handshaking process, and + * is ready for login to start. + */ +static void set_port_online(u64 *fc_regs) +{ + u64 cmdcfg; + + cmdcfg = readq_be(&fc_regs[FC_MTIP_CMDCONFIG / 8]); + cmdcfg &= (~FC_MTIP_CMDCONFIG_OFFLINE); /* clear OFF_LINE */ + cmdcfg |= (FC_MTIP_CMDCONFIG_ONLINE); /* set ON_LINE */ + writeq_be(cmdcfg, &fc_regs[FC_MTIP_CMDCONFIG / 8]); +} + +/** + * set_port_offline() - transitions the specified host FC port to offline state + * @fc_regs: Top of MMIO region defined for specified port. + * + * The provided MMIO region must be mapped prior to call. + */ +static void set_port_offline(u64 *fc_regs) +{ + u64 cmdcfg; + + cmdcfg = readq_be(&fc_regs[FC_MTIP_CMDCONFIG / 8]); + cmdcfg &= (~FC_MTIP_CMDCONFIG_ONLINE); /* clear ON_LINE */ + cmdcfg |= (FC_MTIP_CMDCONFIG_OFFLINE); /* set OFF_LINE */ + writeq_be(cmdcfg, &fc_regs[FC_MTIP_CMDCONFIG / 8]); +} + +/** + * wait_port_online() - waits for the specified host FC port come online + * @fc_regs: Top of MMIO region defined for specified port. + * @delay_us: Number of microseconds to delay between reading port status. + * @nretry: Number of cycles to retry reading port status. + * + * The provided MMIO region must be mapped prior to call. This will timeout + * when the cable is not plugged in. + * + * Return: + * TRUE (1) when the specified port is online + * FALSE (0) when the specified port fails to come online after timeout + * -EINVAL when @delay_us is less than 1000 + */ +static int wait_port_online(u64 *fc_regs, u32 delay_us, u32 nretry) +{ + u64 status; + + if (delay_us < 1000) { + pr_err("%s: invalid delay specified %d\n", __func__, delay_us); + return -EINVAL; + } + + do { + msleep(delay_us / 1000); + status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); + } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE && + nretry--); + + return ((status & FC_MTIP_STATUS_MASK) == FC_MTIP_STATUS_ONLINE); +} + +/** + * wait_port_offline() - waits for the specified host FC port go offline + * @fc_regs: Top of MMIO region defined for specified port. + * @delay_us: Number of microseconds to delay between reading port status. + * @nretry: Number of cycles to retry reading port status. + * + * The provided MMIO region must be mapped prior to call. + * + * Return: + * TRUE (1) when the specified port is offline + * FALSE (0) when the specified port fails to go offline after timeout + * -EINVAL when @delay_us is less than 1000 + */ +static int wait_port_offline(u64 *fc_regs, u32 delay_us, u32 nretry) +{ + u64 status; + + if (delay_us < 1000) { + pr_err("%s: invalid delay specified %d\n", __func__, delay_us); + return -EINVAL; + } + + do { + msleep(delay_us / 1000); + status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); + } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE && + nretry--); + + return ((status & FC_MTIP_STATUS_MASK) == FC_MTIP_STATUS_OFFLINE); +} + +/** + * afu_set_wwpn() - configures the WWPN for the specified host FC port + * @afu: AFU associated with the host that owns the specified FC port. + * @port: Port number being configured. + * @fc_regs: Top of MMIO region defined for specified port. + * @wwpn: The world-wide-port-number previously discovered for port. + * + * The provided MMIO region must be mapped prior to call. As part of the + * sequence to configure the WWPN, the port is toggled offline and then back + * online. This toggling action can cause this routine to delay up to a few + * seconds. When configured to use the internal LUN feature of the AFU, a + * failure to come online is overridden. + * + * Return: + * 0 when the WWPN is successfully written and the port comes back online + * -1 when the port fails to go offline or come back up online + */ +static int afu_set_wwpn(struct afu *afu, int port, u64 *fc_regs, u64 wwpn) +{ + int ret = 0; + + set_port_offline(fc_regs); + + if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, + FC_PORT_STATUS_RETRY_CNT)) { + pr_debug("%s: wait on port %d to go offline timed out\n", + __func__, port); + ret = -1; /* but continue on to leave the port back online */ + } + + if (ret == 0) + writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); + + set_port_online(fc_regs); + + if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, + FC_PORT_STATUS_RETRY_CNT)) { + pr_debug("%s: wait on port %d to go online timed out\n", + __func__, port); + ret = -1; + + /* + * Override for internal lun!!! + */ + if (afu->internal_lun) { + pr_debug("%s: Overriding port %d online timeout!!!\n", + __func__, port); + ret = 0; + } + } + + pr_debug("%s: returning rc=%d\n", __func__, ret); + + return ret; +} + +/** + * afu_link_reset() - resets the specified host FC port + * @afu: AFU associated with the host that owns the specified FC port. + * @port: Port number being configured. + * @fc_regs: Top of MMIO region defined for specified port. + * + * The provided MMIO region must be mapped prior to call. The sequence to + * reset the port involves toggling it offline and then back online. This + * action can cause this routine to delay up to a few seconds. An effort + * is made to maintain link with the device by switching to host to use + * the alternate port exclusively while the reset takes place. + * failure to come online is overridden. + */ +static void afu_link_reset(struct afu *afu, int port, u64 *fc_regs) +{ + u64 port_sel; + + /* first switch the AFU to the other links, if any */ + port_sel = readq_be(&afu->afu_map->global.regs.afu_port_sel); + port_sel &= ~(1 << port); + writeq_be(port_sel, &afu->afu_map->global.regs.afu_port_sel); + cxlflash_afu_sync(afu, 0, 0, AFU_GSYNC); + + set_port_offline(fc_regs); + if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, + FC_PORT_STATUS_RETRY_CNT)) + pr_err("%s: wait on port %d to go offline timed out\n", + __func__, port); + + set_port_online(fc_regs); + if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, + FC_PORT_STATUS_RETRY_CNT)) + pr_err("%s: wait on port %d to go online timed out\n", + __func__, port); + + /* switch back to include this port */ + port_sel |= (1 << port); + writeq_be(port_sel, &afu->afu_map->global.regs.afu_port_sel); + cxlflash_afu_sync(afu, 0, 0, AFU_GSYNC); + + pr_debug("%s: returning port_sel=%lld\n", __func__, port_sel); +} + +/* + * Asynchronous interrupt information table + */ +static const struct asyc_intr_info ainfo[] = { + {SISL_ASTATUS_FC0_OTHER, "other error", 0, CLR_FC_ERROR | LINK_RESET}, + {SISL_ASTATUS_FC0_LOGO, "target initiated LOGO", 0, 0}, + {SISL_ASTATUS_FC0_CRC_T, "CRC threshold exceeded", 0, LINK_RESET}, + {SISL_ASTATUS_FC0_LOGI_R, "login timed out, retrying", 0, 0}, + {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR}, + {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, 0}, + {SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0}, + {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0}, + {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, + {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, + {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET}, + {SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, 0}, + {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, + {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, 0}, + {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0}, + {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0}, + {0x0, "", 0, 0} /* terminator */ +}; + +/** + * find_ainfo() - locates and returns asynchronous interrupt information + * @status: Status code set by AFU on error. + * + * Return: The located information or NULL when the status code is invalid. + */ +static const struct asyc_intr_info *find_ainfo(u64 status) +{ + const struct asyc_intr_info *info; + + for (info = &ainfo[0]; info->status; info++) + if (info->status == status) + return info; + + return NULL; +} + +/** + * afu_err_intr_init() - clears and initializes the AFU for error interrupts + * @afu: AFU associated with the host. + */ +static void afu_err_intr_init(struct afu *afu) +{ + int i; + u64 reg; + + /* global async interrupts: AFU clears afu_ctrl on context exit + * if async interrupts were sent to that context. This prevents + * the AFU form sending further async interrupts when + * there is + * nobody to receive them. + */ + + /* mask all */ + writeq_be(-1ULL, &afu->afu_map->global.regs.aintr_mask); + /* set LISN# to send and point to master context */ + reg = ((u64) (((afu->ctx_hndl << 8) | SISL_MSI_ASYNC_ERROR)) << 40); + + if (afu->internal_lun) + reg |= 1; /* Bit 63 indicates local lun */ + writeq_be(reg, &afu->afu_map->global.regs.afu_ctrl); + /* clear all */ + writeq_be(-1ULL, &afu->afu_map->global.regs.aintr_clear); + /* unmask bits that are of interest */ + /* note: afu can send an interrupt after this step */ + writeq_be(SISL_ASTATUS_MASK, &afu->afu_map->global.regs.aintr_mask); + /* clear again in case a bit came on after previous clear but before */ + /* unmask */ + writeq_be(-1ULL, &afu->afu_map->global.regs.aintr_clear); + + /* Clear/Set internal lun bits */ + reg = readq_be(&afu->afu_map->global.fc_regs[0][FC_CONFIG2 / 8]); + reg &= SISL_FC_INTERNAL_MASK; + if (afu->internal_lun) + reg |= ((u64)(afu->internal_lun - 1) << SISL_FC_INTERNAL_SHIFT); + writeq_be(reg, &afu->afu_map->global.fc_regs[0][FC_CONFIG2 / 8]); + + /* now clear FC errors */ + for (i = 0; i < NUM_FC_PORTS; i++) { + writeq_be(0xFFFFFFFFU, + &afu->afu_map->global.fc_regs[i][FC_ERROR / 8]); + writeq_be(0, &afu->afu_map->global.fc_regs[i][FC_ERRCAP / 8]); + } + + /* sync interrupts for master's IOARRIN write */ + /* note that unlike asyncs, there can be no pending sync interrupts */ + /* at this time (this is a fresh context and master has not written */ + /* IOARRIN yet), so there is nothing to clear. */ + + /* set LISN#, it is always sent to the context that wrote IOARRIN */ + writeq_be(SISL_MSI_SYNC_ERROR, &afu->host_map->ctx_ctrl); + writeq_be(SISL_ISTATUS_MASK, &afu->host_map->intr_mask); +} + +/** + * cxlflash_sync_err_irq() - interrupt handler for synchronous errors + * @irq: Interrupt number. + * @data: Private data provided at interrupt registration, the AFU. + * + * Return: Always return IRQ_HANDLED. + */ +static irqreturn_t cxlflash_sync_err_irq(int irq, void *data) +{ + struct afu *afu = (struct afu *)data; + u64 reg; + u64 reg_unmasked; + + reg = readq_be(&afu->host_map->intr_status); + reg_unmasked = (reg & SISL_ISTATUS_UNMASK); + + if (reg_unmasked == 0UL) { + pr_err("%s: %llX: spurious interrupt, intr_status %016llX\n", + __func__, (u64)afu, reg); + goto cxlflash_sync_err_irq_exit; + } + + pr_err("%s: %llX: unexpected interrupt, intr_status %016llX\n", + __func__, (u64)afu, reg); + + writeq_be(reg_unmasked, &afu->host_map->intr_clear); + +cxlflash_sync_err_irq_exit: + pr_debug("%s: returning rc=%d\n", __func__, IRQ_HANDLED); + return IRQ_HANDLED; +} + +/** + * cxlflash_rrq_irq() - interrupt handler for read-response queue (normal path) + * @irq: Interrupt number. + * @data: Private data provided at interrupt registration, the AFU. + * + * Return: Always return IRQ_HANDLED. + */ +static irqreturn_t cxlflash_rrq_irq(int irq, void *data) +{ + struct afu *afu = (struct afu *)data; + struct afu_cmd *cmd; + bool toggle = afu->toggle; + u64 entry, + *hrrq_start = afu->hrrq_start, + *hrrq_end = afu->hrrq_end, + *hrrq_curr = afu->hrrq_curr; + + /* Process however many RRQ entries that are ready */ + while (true) { + entry = *hrrq_curr; + + if ((entry & SISL_RESP_HANDLE_T_BIT) != toggle) + break; + + cmd = (struct afu_cmd *)(entry & ~SISL_RESP_HANDLE_T_BIT); + cmd_complete(cmd); + + /* Advance to next entry or wrap and flip the toggle bit */ + if (hrrq_curr < hrrq_end) + hrrq_curr++; + else { + hrrq_curr = hrrq_start; + toggle ^= SISL_RESP_HANDLE_T_BIT; + } + } + + afu->hrrq_curr = hrrq_curr; + afu->toggle = toggle; + + return IRQ_HANDLED; +} + +/** + * cxlflash_async_err_irq() - interrupt handler for asynchronous errors + * @irq: Interrupt number. + * @data: Private data provided at interrupt registration, the AFU. + * + * Return: Always return IRQ_HANDLED. + */ +static irqreturn_t cxlflash_async_err_irq(int irq, void *data) +{ + struct afu *afu = (struct afu *)data; + struct cxlflash_cfg *cfg; + u64 reg_unmasked; + const struct asyc_intr_info *info; + struct sisl_global_map *global = &afu->afu_map->global; + u64 reg; + u8 port; + int i; + + cfg = afu->parent; + + reg = readq_be(&global->regs.aintr_status); + reg_unmasked = (reg & SISL_ASTATUS_UNMASK); + + if (reg_unmasked == 0) { + pr_err("%s: spurious interrupt, aintr_status 0x%016llX\n", + __func__, reg); + goto out; + } + + /* it is OK to clear AFU status before FC_ERROR */ + writeq_be(reg_unmasked, &global->regs.aintr_clear); + + /* check each bit that is on */ + for (i = 0; reg_unmasked; i++, reg_unmasked = (reg_unmasked >> 1)) { + info = find_ainfo(1ULL << i); + if ((reg_unmasked & 0x1) || !info) + continue; + + port = info->port; + + pr_err("%s: FC Port %d -> %s, fc_status 0x%08llX\n", + __func__, port, info->desc, + readq_be(&global->fc_regs[port][FC_STATUS / 8])); + + /* + * do link reset first, some OTHER errors will set FC_ERROR + * again if cleared before or w/o a reset + */ + if (info->action & LINK_RESET) { + pr_err("%s: FC Port %d: resetting link\n", + __func__, port); + cfg->lr_state = LINK_RESET_REQUIRED; + cfg->lr_port = port; + schedule_work(&cfg->work_q); + } + + if (info->action & CLR_FC_ERROR) { + reg = readq_be(&global->fc_regs[port][FC_ERROR / 8]); + + /* + * since all errors are unmasked, FC_ERROR and FC_ERRCAP + * should be the same and tracing one is sufficient. + */ + + pr_err("%s: fc %d: clearing fc_error 0x%08llX\n", + __func__, port, reg); + + writeq_be(reg, &global->fc_regs[port][FC_ERROR / 8]); + writeq_be(0, &global->fc_regs[port][FC_ERRCAP / 8]); + } + } + +out: + pr_debug("%s: returning rc=%d, afu=%p\n", __func__, IRQ_HANDLED, afu); + return IRQ_HANDLED; +} + +/** + * start_context() - starts the master context + * @cxlflash: Internal structure associated with the host. + * + * Return: A success or failure value from CXL services. + */ +static int start_context(struct cxlflash_cfg *cfg) +{ + int rc = 0; + + rc = cxl_start_context(cfg->mcctx, + cfg->afu->work.work_element_descriptor, + NULL); + + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * read_vpd() - obtains the WWPNs from VPD + * @cxlflash: Internal structure associated with the host. + * @wwpn: Array of size NUM_FC_PORTS to pass back WWPNs + * + * Return: + * 0 on success + * -ENODEV when VPD or WWPN keywords not found + */ +static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) +{ + struct pci_dev *dev = cfg->parent_dev; + int rc = 0; + int ro_start, ro_size, i, j, k; + ssize_t vpd_size; + char vpd_data[CXLFLASH_VPD_LEN]; + char tmp_buf[WWPN_BUF_LEN] = { 0 }; + char *wwpn_vpd_tags[NUM_FC_PORTS] = { "V5", "V6" }; + + /* Get the VPD data from the device */ + vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data); + if (unlikely(vpd_size <= 0)) { + pr_err("%s: Unable to read VPD (size = %ld)\n", + __func__, vpd_size); + rc = -ENODEV; + goto out; + } + + /* Get the read only section offset */ + ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, + PCI_VPD_LRDT_RO_DATA); + if (unlikely(ro_start < 0)) { + pr_err("%s: VPD Read-only data not found\n", __func__); + rc = -ENODEV; + goto out; + } + + /* Get the read only section size, cap when extends beyond read VPD */ + ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]); + j = ro_size; + i = ro_start + PCI_VPD_LRDT_TAG_SIZE; + if (unlikely((i + j) > vpd_size)) { + pr_debug("%s: Might need to read more VPD (%d > %ld)\n", + __func__, (i + j), vpd_size); + ro_size = vpd_size - i; + } + + /* + * Find the offset of the WWPN tag within the read only + * VPD data and validate the found field (partials are + * no good to us). Convert the ASCII data to an integer + * value. Note that we must copy to a temporary buffer + * because the conversion service requires that the ASCII + * string be terminated. + */ + for (k = 0; k < NUM_FC_PORTS; k++) { + j = ro_size; + i = ro_start + PCI_VPD_LRDT_TAG_SIZE; + + i = pci_vpd_find_info_keyword(vpd_data, i, j, wwpn_vpd_tags[k]); + if (unlikely(i < 0)) { + pr_err("%s: Port %d WWPN not found in VPD\n", + __func__, k); + rc = -ENODEV; + goto out; + } + + j = pci_vpd_info_field_size(&vpd_data[i]); + i += PCI_VPD_INFO_FLD_HDR_SIZE; + if (unlikely((i + j > vpd_size) || (j != WWPN_LEN))) { + pr_err("%s: Port %d WWPN incomplete or VPD corrupt\n", + __func__, k); + rc = -ENODEV; + goto out; + } + + memcpy(tmp_buf, &vpd_data[i], WWPN_LEN); + rc = kstrtoul(tmp_buf, WWPN_LEN, (ulong *)&wwpn[k]); + if (unlikely(rc)) { + pr_err("%s: Fail to convert port %d WWPN to integer\n", + __func__, k); + rc = -ENODEV; + goto out; + } + } + +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_context_reset() - timeout handler for AFU commands + * @cmd: AFU command that timed out. + * + * Sends a reset to the AFU. + */ +void cxlflash_context_reset(struct afu_cmd *cmd) +{ + int nretry = 0; + u64 rrin = 0x1; + u64 room = 0; + struct afu *afu = cmd->parent; + ulong lock_flags; + + pr_debug("%s: cmd=%p\n", __func__, cmd); + + spin_lock_irqsave(&cmd->slock, lock_flags); + + /* Already completed? */ + if (cmd->sa.host_use_b[0] & B_DONE) { + spin_unlock_irqrestore(&cmd->slock, lock_flags); + return; + } + + cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT); + spin_unlock_irqrestore(&cmd->slock, lock_flags); + + /* + * We really want to send this reset at all costs, so spread + * out wait time on successive retries for available room. + */ + do { + room = readq_be(&afu->host_map->cmd_room); + atomic64_set(&afu->room, room); + if (room) + goto write_rrin; + udelay(nretry); + } while (nretry++ < MC_ROOM_RETRY_CNT); + + pr_err("%s: no cmd_room to send reset\n", __func__); + return; + +write_rrin: + nretry = 0; + writeq_be(rrin, &afu->host_map->ioarrin); + do { + rrin = readq_be(&afu->host_map->ioarrin); + if (rrin != 0x1) + break; + /* Double delay each time */ + udelay(2 ^ nretry); + } while (nretry++ < MC_ROOM_RETRY_CNT); +} + +/** + * init_pcr() - initialize the provisioning and control registers + * @cxlflash: Internal structure associated with the host. + * + * Also sets up fast access to the mapped registers and initializes AFU + * command fields that never change. + */ +void init_pcr(struct cxlflash_cfg *cfg) +{ + struct afu *afu = cfg->afu; + struct sisl_ctrl_map *ctrl_map; + int i; + + for (i = 0; i < MAX_CONTEXT; i++) { + ctrl_map = &afu->afu_map->ctrls[i].ctrl; + /* disrupt any clients that could be running */ + /* e. g. clients that survived a master restart */ + writeq_be(0, &ctrl_map->rht_start); + writeq_be(0, &ctrl_map->rht_cnt_id); + writeq_be(0, &ctrl_map->ctx_cap); + } + + /* copy frequently used fields into afu */ + afu->ctx_hndl = (u16) cxl_process_element(cfg->mcctx); + /* ctx_hndl is 16 bits in CAIA */ + afu->host_map = &afu->afu_map->hosts[afu->ctx_hndl].host; + afu->ctrl_map = &afu->afu_map->ctrls[afu->ctx_hndl].ctrl; + + /* Program the Endian Control for the master context */ + writeq_be(SISL_ENDIAN_CTRL, &afu->host_map->endian_ctrl); + + /* initialize cmd fields that never change */ + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { + afu->cmd[i].rcb.ctx_id = afu->ctx_hndl; + afu->cmd[i].rcb.msi = SISL_MSI_RRQ_UPDATED; + afu->cmd[i].rcb.rrq = 0x0; + } +} + +/** + * init_global() - initialize AFU global registers + * @cxlflash: Internal structure associated with the host. + */ +int init_global(struct cxlflash_cfg *cfg) +{ + struct afu *afu = cfg->afu; + u64 wwpn[NUM_FC_PORTS]; /* wwpn of AFU ports */ + int i = 0, num_ports = 0; + int rc = 0; + u64 reg; + + rc = read_vpd(cfg, &wwpn[0]); + if (rc) { + pr_err("%s: could not read vpd rc=%d\n", __func__, rc); + goto out; + } + + pr_debug("%s: wwpn0=0x%llX wwpn1=0x%llX\n", __func__, wwpn[0], wwpn[1]); + + /* set up RRQ in AFU for master issued cmds */ + writeq_be((u64) afu->hrrq_start, &afu->host_map->rrq_start); + writeq_be((u64) afu->hrrq_end, &afu->host_map->rrq_end); + + /* AFU configuration */ + reg = readq_be(&afu->afu_map->global.regs.afu_config); + reg |= SISL_AFUCONF_AR_ALL|SISL_AFUCONF_ENDIAN; + /* enable all auto retry options and control endianness */ + /* leave others at default: */ + /* CTX_CAP write protected, mbox_r does not clear on read and */ + /* checker on if dual afu */ + writeq_be(reg, &afu->afu_map->global.regs.afu_config); + + /* global port select: select either port */ + if (afu->internal_lun) { + /* only use port 0 */ + writeq_be(PORT0, &afu->afu_map->global.regs.afu_port_sel); + num_ports = NUM_FC_PORTS - 1; + } else { + writeq_be(BOTH_PORTS, &afu->afu_map->global.regs.afu_port_sel); + num_ports = NUM_FC_PORTS; + } + + for (i = 0; i < num_ports; i++) { + /* unmask all errors (but they are still masked at AFU) */ + writeq_be(0, &afu->afu_map->global.fc_regs[i][FC_ERRMSK / 8]); + /* clear CRC error cnt & set a threshold */ + (void)readq_be(&afu->afu_map->global. + fc_regs[i][FC_CNT_CRCERR / 8]); + writeq_be(MC_CRC_THRESH, &afu->afu_map->global.fc_regs[i] + [FC_CRC_THRESH / 8]); + + /* set WWPNs. If already programmed, wwpn[i] is 0 */ + if (wwpn[i] != 0 && + afu_set_wwpn(afu, i, + &afu->afu_map->global.fc_regs[i][0], + wwpn[i])) { + pr_err("%s: failed to set WWPN on port %d\n", + __func__, i); + rc = -EIO; + goto out; + } + /* Programming WWPN back to back causes additional + * offline/online transitions and a PLOGI + */ + msleep(100); + + } + + /* set up master's own CTX_CAP to allow real mode, host translation */ + /* tbls, afu cmds and read/write GSCSI cmds. */ + /* First, unlock ctx_cap write by reading mbox */ + (void)readq_be(&afu->ctrl_map->mbox_r); /* unlock ctx_cap */ + writeq_be((SISL_CTX_CAP_REAL_MODE | SISL_CTX_CAP_HOST_XLATE | + SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD | + SISL_CTX_CAP_AFU_CMD | SISL_CTX_CAP_GSCSI_CMD), + &afu->ctrl_map->ctx_cap); + /* init heartbeat */ + afu->hb = readq_be(&afu->afu_map->global.regs.afu_hb); + +out: + return rc; +} + +/** + * start_afu() - initializes and starts the AFU + * @cxlflash: Internal structure associated with the host. + */ +static int start_afu(struct cxlflash_cfg *cfg) +{ + struct afu *afu = cfg->afu; + struct afu_cmd *cmd; + + int i = 0; + int rc = 0; + + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) { + cmd = &afu->cmd[i]; + + init_completion(&cmd->cevent); + spin_lock_init(&cmd->slock); + cmd->parent = afu; + } + + init_pcr(cfg); + + /* initialize RRQ pointers */ + afu->hrrq_start = &afu->rrq_entry[0]; + afu->hrrq_end = &afu->rrq_entry[NUM_RRQ_ENTRY - 1]; + afu->hrrq_curr = afu->hrrq_start; + afu->toggle = 1; + + rc = init_global(cfg); + + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * init_mc() - create and register as the master context + * @cxlflash: Internal structure associated with the host. + * + * Return: + * 0 on success + * -ENOMEM when unable to obtain a context from CXL services + * A failure value from CXL services. + */ +static int init_mc(struct cxlflash_cfg *cfg) +{ + struct cxl_context *ctx; + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + int rc = 0; + enum undo_level level; + + ctx = cxl_get_context(cfg->dev); + if (unlikely(!ctx)) + return -ENOMEM; + cfg->mcctx = ctx; + + /* Set it up as a master with the CXL */ + cxl_set_master(ctx); + + /* During initialization reset the AFU to start from a clean slate */ + rc = cxl_afu_reset(cfg->mcctx); + if (unlikely(rc)) { + dev_err(dev, "%s: initial AFU reset failed rc=%d\n", + __func__, rc); + level = RELEASE_CONTEXT; + goto out; + } + + rc = cxl_allocate_afu_irqs(ctx, 3); + if (unlikely(rc)) { + dev_err(dev, "%s: call to allocate_afu_irqs failed rc=%d!\n", + __func__, rc); + level = RELEASE_CONTEXT; + goto out; + } + + rc = cxl_map_afu_irq(ctx, 1, cxlflash_sync_err_irq, afu, + "SISL_MSI_SYNC_ERROR"); + if (unlikely(rc <= 0)) { + dev_err(dev, "%s: IRQ 1 (SISL_MSI_SYNC_ERROR) map failed!\n", + __func__); + level = FREE_IRQ; + goto out; + } + + rc = cxl_map_afu_irq(ctx, 2, cxlflash_rrq_irq, afu, + "SISL_MSI_RRQ_UPDATED"); + if (unlikely(rc <= 0)) { + dev_err(dev, "%s: IRQ 2 (SISL_MSI_RRQ_UPDATED) map failed!\n", + __func__); + level = UNMAP_ONE; + goto out; + } + + rc = cxl_map_afu_irq(ctx, 3, cxlflash_async_err_irq, afu, + "SISL_MSI_ASYNC_ERROR"); + if (unlikely(rc <= 0)) { + dev_err(dev, "%s: IRQ 3 (SISL_MSI_ASYNC_ERROR) map failed!\n", + __func__); + level = UNMAP_TWO; + goto out; + } + + rc = 0; + + /* This performs the equivalent of the CXL_IOCTL_START_WORK. + * The CXL_IOCTL_GET_PROCESS_ELEMENT is implicit in the process + * element (pe) that is embedded in the context (ctx) + */ + rc = start_context(cfg); + if (unlikely(rc)) { + dev_err(dev, "%s: start context failed rc=%d\n", __func__, rc); + level = UNMAP_THREE; + goto out; + } +ret: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +out: + term_mc(cfg, level); + goto ret; +} + +/** + * init_afu() - setup as master context and start AFU + * @cxlflash: Internal structure associated with the host. + * + * This routine is a higher level of control for configuring the + * AFU on probe and reset paths. + * + * Return: + * 0 on success + * -ENOMEM when unable to map the AFU MMIO space + * A failure value from internal services. + */ +static int init_afu(struct cxlflash_cfg *cfg) +{ + u64 reg; + int rc = 0; + struct afu *afu = cfg->afu; + struct device *dev = &cfg->dev->dev; + + rc = init_mc(cfg); + if (rc) { + dev_err(dev, "%s: call to init_mc failed, rc=%d!\n", + __func__, rc); + goto err1; + } + + /* Map the entire MMIO space of the AFU. + */ + afu->afu_map = cxl_psa_map(cfg->mcctx); + if (!afu->afu_map) { + rc = -ENOMEM; + term_mc(cfg, UNDO_START); + dev_err(dev, "%s: call to cxl_psa_map failed!\n", __func__); + goto err1; + } + + /* don't byte reverse on reading afu_version, else the string form */ + /* will be backwards */ + reg = afu->afu_map->global.regs.afu_version; + memcpy(afu->version, ®, 8); + afu->interface_version = + readq_be(&afu->afu_map->global.regs.interface_version); + pr_debug("%s: afu version %s, interface version 0x%llX\n", + __func__, afu->version, afu->interface_version); + + rc = start_afu(cfg); + if (rc) { + dev_err(dev, "%s: call to start_afu failed, rc=%d!\n", + __func__, rc); + term_mc(cfg, UNDO_START); + cxl_psa_unmap((void *)afu->afu_map); + afu->afu_map = NULL; + goto err1; + } + + afu_err_intr_init(cfg->afu); + atomic64_set(&afu->room, readq_be(&afu->host_map->cmd_room)); + +err1: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_send_cmd() - sends an AFU command + * @afu: AFU associated with the host. + * @cmd: AFU command to send. + * + * Return: + * 0 on success + * -1 on failure + */ +int cxlflash_send_cmd(struct afu *afu, struct afu_cmd *cmd) +{ + struct cxlflash_cfg *cfg = afu->parent; + int nretry = 0; + int rc = 0; + u64 room; + long newval; + + /* + * This routine is used by critical users such an AFU sync and to + * send a task management function (TMF). Thus we want to retry a + * bit before returning an error. To avoid the performance penalty + * of MMIO, we spread the update of 'room' over multiple commands. + */ +retry: + newval = atomic64_dec_if_positive(&afu->room); + if (!newval) { + do { + room = readq_be(&afu->host_map->cmd_room); + atomic64_set(&afu->room, room); + if (room) + goto write_ioarrin; + udelay(nretry); + } while (nretry++ < MC_ROOM_RETRY_CNT); + + pr_err("%s: no cmd_room to send 0x%X\n", + __func__, cmd->rcb.cdb[0]); + + goto no_room; + } else if (unlikely(newval < 0)) { + /* This should be rare. i.e. Only if two threads race and + * decrement before the MMIO read is done. In this case + * just benefit from the other thread having updated + * afu->room. + */ + if (nretry++ < MC_ROOM_RETRY_CNT) { + udelay(nretry); + goto retry; + } + + goto no_room; + } + +write_ioarrin: + writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin); +out: + pr_debug("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd, + cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc); + return rc; + +no_room: + afu->read_room = true; + schedule_work(&cfg->work_q); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; +} + +/** + * cxlflash_wait_resp() - polls for a response or timeout to a sent AFU command + * @afu: AFU associated with the host. + * @cmd: AFU command that was sent. + */ +void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd) +{ + ulong timeout = jiffies + (cmd->rcb.timeout * 2 * HZ); + + timeout = wait_for_completion_timeout(&cmd->cevent, timeout); + if (!timeout) + cxlflash_context_reset(cmd); + + if (unlikely(cmd->sa.ioasc != 0)) + pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, " + "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0], + cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc, + cmd->sa.rc.fc_rc); +} + +/** + * cxlflash_afu_sync() - builds and sends an AFU sync command + * @afu: AFU associated with the host. + * @ctx_hndl_u: Identifies context requesting sync. + * @res_hndl_u: Identifies resource requesting sync. + * @mode: Type of sync to issue (lightweight, heavyweight, global). + * + * The AFU can only take 1 sync command at a time. This routine enforces this + * limitation by using a mutex to provide exlusive access to the AFU during + * the sync. This design point requires calling threads to not be on interrupt + * context due to the possibility of sleeping during concurrent sync operations. + * + * Return: + * 0 on success + * -1 on failure + */ +int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, + res_hndl_t res_hndl_u, u8 mode) +{ + struct afu_cmd *cmd = NULL; + int rc = 0; + int retry_cnt = 0; + static DEFINE_MUTEX(sync_active); + + mutex_lock(&sync_active); +retry: + cmd = cxlflash_cmd_checkout(afu); + if (unlikely(!cmd)) { + retry_cnt++; + udelay(1000 * retry_cnt); + if (retry_cnt < MC_RETRY_CNT) + goto retry; + pr_err("%s: could not get a free command\n", __func__); + rc = -1; + goto out; + } + + pr_debug("%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u); + + memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb)); + + cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD; + cmd->rcb.port_sel = 0x0; /* NA */ + cmd->rcb.lun_id = 0x0; /* NA */ + cmd->rcb.data_len = 0x0; + cmd->rcb.data_ea = 0x0; + cmd->rcb.timeout = MC_AFU_SYNC_TIMEOUT; + + cmd->rcb.cdb[0] = 0xC0; /* AFU Sync */ + cmd->rcb.cdb[1] = mode; + + /* The cdb is aligned, no unaligned accessors required */ + *((u16 *)&cmd->rcb.cdb[2]) = swab16(ctx_hndl_u); + *((u32 *)&cmd->rcb.cdb[4]) = swab32(res_hndl_u); + + rc = cxlflash_send_cmd(afu, cmd); + if (unlikely(rc)) + goto out; + + cxlflash_wait_resp(afu, cmd); + + /* set on timeout */ + if (unlikely((cmd->sa.ioasc != 0) || + (cmd->sa.host_use_b[0] & B_ERROR))) + rc = -1; +out: + mutex_unlock(&sync_active); + if (cmd) + cxlflash_cmd_checkin(cmd); + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_afu_reset() - resets the AFU + * @cxlflash: Internal structure associated with the host. + * + * Return: + * 0 on success + * A failure value from internal services. + */ +int cxlflash_afu_reset(struct cxlflash_cfg *cfg) +{ + int rc = 0; + /* Stop the context before the reset. Since the context is + * no longer available restart it after the reset is complete + */ + + term_afu(cfg); + + rc = init_afu(cfg); + + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_worker_thread() - work thread handler for the AFU + * @work: Work structure contained within cxlflash associated with host. + * + * Handles the following events: + * - Link reset which cannot be performed on interrupt context due to + * blocking up to a few seconds + * - Read AFU command room + */ +static void cxlflash_worker_thread(struct work_struct *work) +{ + struct cxlflash_cfg *cfg = + container_of(work, struct cxlflash_cfg, work_q); + struct afu *afu = cfg->afu; + int port; + ulong lock_flags; + + spin_lock_irqsave(cfg->host->host_lock, lock_flags); + + if (cfg->lr_state == LINK_RESET_REQUIRED) { + port = cfg->lr_port; + if (port < 0) + pr_err("%s: invalid port index %d\n", __func__, port); + else { + spin_unlock_irqrestore(cfg->host->host_lock, + lock_flags); + + /* The reset can block... */ + afu_link_reset(afu, port, + &afu->afu_map-> + global.fc_regs[port][0]); + spin_lock_irqsave(cfg->host->host_lock, lock_flags); + } + + cfg->lr_state = LINK_RESET_COMPLETE; + } + + if (afu->read_room) { + atomic64_set(&afu->room, readq_be(&afu->host_map->cmd_room)); + afu->read_room = false; + } + + spin_unlock_irqrestore(cfg->host->host_lock, lock_flags); +} + +/** + * cxlflash_probe() - PCI entry point to add host + * @pdev: PCI device associated with the host. + * @dev_id: PCI device id associated with device. + * + * Return: 0 on success / non-zero on failure + */ +static int cxlflash_probe(struct pci_dev *pdev, + const struct pci_device_id *dev_id) +{ + struct Scsi_Host *host; + struct cxlflash_cfg *cfg = NULL; + struct device *phys_dev; + struct dev_dependent_vals *ddv; + int rc = 0; + + dev_dbg(&pdev->dev, "%s: Found CXLFLASH with IRQ: %d\n", + __func__, pdev->irq); + + ddv = (struct dev_dependent_vals *)dev_id->driver_data; + driver_template.max_sectors = ddv->max_sectors; + + host = scsi_host_alloc(&driver_template, sizeof(struct cxlflash_cfg)); + if (!host) { + dev_err(&pdev->dev, "%s: call to scsi_host_alloc failed!\n", + __func__); + rc = -ENOMEM; + goto out; + } + + host->max_id = CXLFLASH_MAX_NUM_TARGETS_PER_BUS; + host->max_lun = CXLFLASH_MAX_NUM_LUNS_PER_TARGET; + host->max_channel = NUM_FC_PORTS - 1; + host->unique_id = host->host_no; + host->max_cmd_len = CXLFLASH_MAX_CDB_LEN; + + cfg = (struct cxlflash_cfg *)host->hostdata; + cfg->host = host; + rc = alloc_mem(cfg); + if (rc) { + dev_err(&pdev->dev, "%s: call to scsi_host_alloc failed!\n", + __func__); + rc = -ENOMEM; + goto out; + } + + cfg->init_state = INIT_STATE_NONE; + cfg->dev = pdev; + cfg->dev_id = (struct pci_device_id *)dev_id; + cfg->mcctx = NULL; + cfg->err_recovery_active = 0; + + init_waitqueue_head(&cfg->tmf_waitq); + init_waitqueue_head(&cfg->eeh_waitq); + + INIT_WORK(&cfg->work_q, cxlflash_worker_thread); + cfg->lr_state = LINK_RESET_INVALID; + cfg->lr_port = -1; + + pci_set_drvdata(pdev, cfg); + + /* Use the special service provided to look up the physical + * PCI device, since we are called on the probe of the virtual + * PCI host bus (vphb) + */ + phys_dev = cxl_get_phys_dev(pdev); + if (!dev_is_pci(phys_dev)) { + pr_err("%s: not a pci dev\n", __func__); + rc = -ENODEV; + goto out_remove; + } + cfg->parent_dev = to_pci_dev(phys_dev); + + cfg->cxl_afu = cxl_pci_to_afu(pdev); + + rc = init_pci(cfg); + if (rc) { + dev_err(&pdev->dev, "%s: call to init_pci " + "failed rc=%d!\n", __func__, rc); + goto out_remove; + } + cfg->init_state = INIT_STATE_PCI; + + rc = init_afu(cfg); + if (rc) { + dev_err(&pdev->dev, "%s: call to init_afu " + "failed rc=%d!\n", __func__, rc); + goto out_remove; + } + cfg->init_state = INIT_STATE_AFU; + + + rc = init_scsi(cfg); + if (rc) { + dev_err(&pdev->dev, "%s: call to init_scsi " + "failed rc=%d!\n", __func__, rc); + goto out_remove; + } + cfg->init_state = INIT_STATE_SCSI; + +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; + +out_remove: + cxlflash_remove(pdev); + goto out; +} + +/* + * PCI device structure + */ +static struct pci_driver cxlflash_driver = { + .name = CXLFLASH_NAME, + .id_table = cxlflash_pci_table, + .probe = cxlflash_probe, + .remove = cxlflash_remove, +}; + +/** + * init_cxlflash() - module entry point + * + * Return: 0 on success / non-zero on failure + */ +static int __init init_cxlflash(void) +{ + pr_info("%s: IBM Power CXL Flash Adapter: %s\n", + __func__, CXLFLASH_DRIVER_DATE); + + return pci_register_driver(&cxlflash_driver); +} + +/** + * exit_cxlflash() - module exit point + */ +static void __exit exit_cxlflash(void) +{ + pci_unregister_driver(&cxlflash_driver); +} + +module_init(init_cxlflash); +module_exit(exit_cxlflash); diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h new file mode 100644 index 000000000000..7f890ccf3289 --- /dev/null +++ b/drivers/scsi/cxlflash/main.h @@ -0,0 +1,104 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _CXLFLASH_MAIN_H +#define _CXLFLASH_MAIN_H + +#include +#include +#include +#include + +#define CXLFLASH_NAME "cxlflash" +#define CXLFLASH_ADAPTER_NAME "IBM POWER CXL Flash Adapter" +#define CXLFLASH_DRIVER_DATE "(June 2, 2015)" + +#define PCI_DEVICE_ID_IBM_CORSA 0x04F0 +#define CXLFLASH_SUBS_DEV_ID 0x04F0 + +/* Since there is only one target, make it 0 */ +#define CXLFLASH_TARGET 0 +#define CXLFLASH_MAX_CDB_LEN 16 + +/* Really only one target per bus since the Texan is directly attached */ +#define CXLFLASH_MAX_NUM_TARGETS_PER_BUS 1 +#define CXLFLASH_MAX_NUM_LUNS_PER_TARGET 65536 + +#define CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT (120 * HZ) + +#define NUM_FC_PORTS CXLFLASH_NUM_FC_PORTS /* ports per AFU */ + +/* FC defines */ +#define FC_MTIP_CMDCONFIG 0x010 +#define FC_MTIP_STATUS 0x018 + +#define FC_PNAME 0x300 +#define FC_CONFIG 0x320 +#define FC_CONFIG2 0x328 +#define FC_STATUS 0x330 +#define FC_ERROR 0x380 +#define FC_ERRCAP 0x388 +#define FC_ERRMSK 0x390 +#define FC_CNT_CRCERR 0x538 +#define FC_CRC_THRESH 0x580 + +#define FC_MTIP_CMDCONFIG_ONLINE 0x20ULL +#define FC_MTIP_CMDCONFIG_OFFLINE 0x40ULL + +#define FC_MTIP_STATUS_MASK 0x30ULL +#define FC_MTIP_STATUS_ONLINE 0x20ULL +#define FC_MTIP_STATUS_OFFLINE 0x10ULL + +/* TIMEOUT and RETRY definitions */ + +/* AFU command timeout values */ +#define MC_AFU_SYNC_TIMEOUT 5 /* 5 secs */ + +/* AFU command room retry limit */ +#define MC_ROOM_RETRY_CNT 10 + +/* FC CRC clear periodic timer */ +#define MC_CRC_THRESH 100 /* threshold in 5 mins */ + +#define FC_PORT_STATUS_RETRY_CNT 100 /* 100 100ms retries = 10 seconds */ +#define FC_PORT_STATUS_RETRY_INTERVAL_US 100000 /* microseconds */ + +/* VPD defines */ +#define CXLFLASH_VPD_LEN 256 +#define WWPN_LEN 16 +#define WWPN_BUF_LEN (WWPN_LEN + 1) + +enum undo_level { + RELEASE_CONTEXT = 0, + FREE_IRQ, + UNMAP_ONE, + UNMAP_TWO, + UNMAP_THREE, + UNDO_START +}; + +struct dev_dependent_vals { + u64 max_sectors; +}; + +struct asyc_intr_info { + u64 status; + char *desc; + u8 port; + u8 action; +#define CLR_FC_ERROR 0x01 +#define LINK_RESET 0x02 +}; + +#endif /* _CXLFLASH_MAIN_H */ diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h new file mode 100755 index 000000000000..bf5d39978630 --- /dev/null +++ b/drivers/scsi/cxlflash/sislite.h @@ -0,0 +1,465 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SISLITE_H +#define _SISLITE_H + +#include + +typedef u16 ctx_hndl_t; +typedef u32 res_hndl_t; + +#define SIZE_4K 4096 +#define SIZE_64K 65536 + +/* + * IOARCB: 64 bytes, min 16 byte alignment required, host native endianness + * except for SCSI CDB which remains big endian per SCSI standards. + */ +struct sisl_ioarcb { + u16 ctx_id; /* ctx_hndl_t */ + u16 req_flags; +#define SISL_REQ_FLAGS_RES_HNDL 0x8000U /* bit 0 (MSB) */ +#define SISL_REQ_FLAGS_PORT_LUN_ID 0x0000U + +#define SISL_REQ_FLAGS_SUP_UNDERRUN 0x4000U /* bit 1 */ + +#define SISL_REQ_FLAGS_TIMEOUT_SECS 0x0000U /* bits 8,9 */ +#define SISL_REQ_FLAGS_TIMEOUT_MSECS 0x0040U +#define SISL_REQ_FLAGS_TIMEOUT_USECS 0x0080U +#define SISL_REQ_FLAGS_TIMEOUT_CYCLES 0x00C0U + +#define SISL_REQ_FLAGS_TMF_CMD 0x0004u /* bit 13 */ + +#define SISL_REQ_FLAGS_AFU_CMD 0x0002U /* bit 14 */ + +#define SISL_REQ_FLAGS_HOST_WRITE 0x0001U /* bit 15 (LSB) */ +#define SISL_REQ_FLAGS_HOST_READ 0x0000U + + union { + u32 res_hndl; /* res_hndl_t */ + u32 port_sel; /* this is a selection mask: + * 0x1 -> port#0 can be selected, + * 0x2 -> port#1 can be selected. + * Can be bitwise ORed. + */ + }; + u64 lun_id; + u32 data_len; /* 4K for read/write */ + u32 ioadl_len; + union { + u64 data_ea; /* min 16 byte aligned */ + u64 ioadl_ea; + }; + u8 msi; /* LISN to send on RRQ write */ +#define SISL_MSI_CXL_PFAULT 0 /* reserved for CXL page faults */ +#define SISL_MSI_SYNC_ERROR 1 /* recommended for AFU sync error */ +#define SISL_MSI_RRQ_UPDATED 2 /* recommended for IO completion */ +#define SISL_MSI_ASYNC_ERROR 3 /* master only - for AFU async error */ + + u8 rrq; /* 0 for a single RRQ */ + u16 timeout; /* in units specified by req_flags */ + u32 rsvd1; + u8 cdb[16]; /* must be in big endian */ + struct scsi_cmnd *scp; +} __packed; + +struct sisl_rc { + u8 flags; +#define SISL_RC_FLAGS_SENSE_VALID 0x80U +#define SISL_RC_FLAGS_FCP_RSP_CODE_VALID 0x40U +#define SISL_RC_FLAGS_OVERRUN 0x20U +#define SISL_RC_FLAGS_UNDERRUN 0x10U + + u8 afu_rc; +#define SISL_AFU_RC_RHT_INVALID 0x01U /* user error */ +#define SISL_AFU_RC_RHT_UNALIGNED 0x02U /* should never happen */ +#define SISL_AFU_RC_RHT_OUT_OF_BOUNDS 0x03u /* user error */ +#define SISL_AFU_RC_RHT_DMA_ERR 0x04u /* see afu_extra + may retry if afu_retry is off + possible on master exit + */ +#define SISL_AFU_RC_RHT_RW_PERM 0x05u /* no RW perms, user error */ +#define SISL_AFU_RC_LXT_UNALIGNED 0x12U /* should never happen */ +#define SISL_AFU_RC_LXT_OUT_OF_BOUNDS 0x13u /* user error */ +#define SISL_AFU_RC_LXT_DMA_ERR 0x14u /* see afu_extra + may retry if afu_retry is off + possible on master exit + */ +#define SISL_AFU_RC_LXT_RW_PERM 0x15u /* no RW perms, user error */ + +#define SISL_AFU_RC_NOT_XLATE_HOST 0x1au /* possible if master exited */ + + /* NO_CHANNELS means the FC ports selected by dest_port in + * IOARCB or in the LXT entry are down when the AFU tried to select + * a FC port. If the port went down on an active IO, it will set + * fc_rc to =0x54(NOLOGI) or 0x57(LINKDOWN) instead. + */ +#define SISL_AFU_RC_NO_CHANNELS 0x20U /* see afu_extra, may retry */ +#define SISL_AFU_RC_CAP_VIOLATION 0x21U /* either user error or + afu reset/master restart + */ +#define SISL_AFU_RC_OUT_OF_DATA_BUFS 0x30U /* always retry */ +#define SISL_AFU_RC_DATA_DMA_ERR 0x31U /* see afu_extra + may retry if afu_retry is off + */ + + u8 scsi_rc; /* SCSI status byte, retry as appropriate */ +#define SISL_SCSI_RC_CHECK 0x02U +#define SISL_SCSI_RC_BUSY 0x08u + + u8 fc_rc; /* retry */ + /* + * We should only see fc_rc=0x57 (LINKDOWN) or 0x54(NOLOGI) for + * commands that are in flight when a link goes down or is logged out. + * If the link is down or logged out before AFU selects the port, either + * it will choose the other port or we will get afu_rc=0x20 (no_channel) + * if there is no valid port to use. + * + * ABORTPEND/ABORTOK/ABORTFAIL/TGTABORT can be retried, typically these + * would happen if a frame is dropped and something times out. + * NOLOGI or LINKDOWN can be retried if the other port is up. + * RESIDERR can be retried as well. + * + * ABORTFAIL might indicate that lots of frames are getting CRC errors. + * So it maybe retried once and reset the link if it happens again. + * The link can also be reset on the CRC error threshold interrupt. + */ +#define SISL_FC_RC_ABORTPEND 0x52 /* exchange timeout or abort request */ +#define SISL_FC_RC_WRABORTPEND 0x53 /* due to write XFER_RDY invalid */ +#define SISL_FC_RC_NOLOGI 0x54 /* port not logged in, in-flight cmds */ +#define SISL_FC_RC_NOEXP 0x55 /* FC protocol error or HW bug */ +#define SISL_FC_RC_INUSE 0x56 /* tag already in use, HW bug */ +#define SISL_FC_RC_LINKDOWN 0x57 /* link down, in-flight cmds */ +#define SISL_FC_RC_ABORTOK 0x58 /* pending abort completed w/success */ +#define SISL_FC_RC_ABORTFAIL 0x59 /* pending abort completed w/fail */ +#define SISL_FC_RC_RESID 0x5A /* ioasa underrun/overrun flags set */ +#define SISL_FC_RC_RESIDERR 0x5B /* actual data len does not match SCSI + reported len, possbly due to dropped + frames */ +#define SISL_FC_RC_TGTABORT 0x5C /* command aborted by target */ +}; + +#define SISL_SENSE_DATA_LEN 20 /* Sense data length */ + +/* + * IOASA: 64 bytes & must follow IOARCB, min 16 byte alignment required, + * host native endianness + */ +struct sisl_ioasa { + union { + struct sisl_rc rc; + u32 ioasc; +#define SISL_IOASC_GOOD_COMPLETION 0x00000000U + }; + u32 resid; + u8 port; + u8 afu_extra; + /* when afu_rc=0x04, 0x14, 0x31 (_xxx_DMA_ERR): + * afu_exta contains PSL response code. Useful codes are: + */ +#define SISL_AFU_DMA_ERR_PAGE_IN 0x0A /* AFU_retry_on_pagein Action + * Enabled N/A + * Disabled retry + */ +#define SISL_AFU_DMA_ERR_INVALID_EA 0x0B /* this is a hard error + * afu_rc Implies + * 0x04, 0x14 master exit. + * 0x31 user error. + */ + /* when afu rc=0x20 (no channels): + * afu_extra bits [4:5]: available portmask, [6:7]: requested portmask. + */ +#define SISL_AFU_NO_CLANNELS_AMASK(afu_extra) (((afu_extra) & 0x0C) >> 2) +#define SISL_AFU_NO_CLANNELS_RMASK(afu_extra) ((afu_extra) & 0x03) + + u8 scsi_extra; + u8 fc_extra; + u8 sense_data[SISL_SENSE_DATA_LEN]; + + /* These fields are defined by the SISlite architecture for the + * host to use as they see fit for their implementation. + */ + union { + u64 host_use[4]; + u8 host_use_b[32]; + }; +} __packed; + +#define SISL_RESP_HANDLE_T_BIT 0x1ULL /* Toggle bit */ + +/* MMIO space is required to support only 64-bit access */ + +/* + * This AFU has two mechanisms to deal with endian-ness. + * One is a global configuration (in the afu_config) register + * below that specifies the endian-ness of the host. + * The other is a per context (i.e. application) specification + * controlled by the endian_ctrl field here. Since the master + * context is one such application the master context's + * endian-ness is set to be the same as the host. + * + * As per the SISlite spec, the MMIO registers are always + * big endian. + */ +#define SISL_ENDIAN_CTRL_BE 0x8000000000000080ULL +#define SISL_ENDIAN_CTRL_LE 0x0000000000000000ULL + +#ifdef __BIG_ENDIAN +#define SISL_ENDIAN_CTRL SISL_ENDIAN_CTRL_BE +#else +#define SISL_ENDIAN_CTRL SISL_ENDIAN_CTRL_LE +#endif + +/* per context host transport MMIO */ +struct sisl_host_map { + __be64 endian_ctrl; /* Per context Endian Control. The AFU will + * operate on whatever the context is of the + * host application. + */ + + __be64 intr_status; /* this sends LISN# programmed in ctx_ctrl. + * Only recovery in a PERM_ERR is a context + * exit since there is no way to tell which + * command caused the error. + */ +#define SISL_ISTATUS_PERM_ERR_CMDROOM 0x0010ULL /* b59, user error */ +#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */ +#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */ +#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE 0x0002ULL /* b62, user error */ + /* Page in wait accessing RCB/IOASA/RRQ is reported in b63. + * Same error in data/LXT/RHT access is reported via IOASA. + */ +#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can be generated + * only when AFU auto + * retry is disabled. + * If user can determine + * the command that + * caused the error, it + * can be retried. + */ +#define SISL_ISTATUS_UNMASK (0x001FULL) /* 1 means unmasked */ +#define SISL_ISTATUS_MASK ~(SISL_ISTATUS_UNMASK) /* 1 means masked */ + + __be64 intr_clear; + __be64 intr_mask; + __be64 ioarrin; /* only write what cmd_room permits */ + __be64 rrq_start; /* start & end are both inclusive */ + __be64 rrq_end; /* write sequence: start followed by end */ + __be64 cmd_room; + __be64 ctx_ctrl; /* least signiifcant byte or b56:63 is LISN# */ + __be64 mbox_w; /* restricted use */ +}; + +/* per context provisioning & control MMIO */ +struct sisl_ctrl_map { + __be64 rht_start; + __be64 rht_cnt_id; + /* both cnt & ctx_id args must be ULL */ +#define SISL_RHT_CNT_ID(cnt, ctx_id) (((cnt) << 48) | ((ctx_id) << 32)) + + __be64 ctx_cap; /* afu_rc below is when the capability is violated */ +#define SISL_CTX_CAP_PROXY_ISSUE 0x8000000000000000ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_REAL_MODE 0x4000000000000000ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_HOST_XLATE 0x2000000000000000ULL /* afu_rc 0x1a */ +#define SISL_CTX_CAP_PROXY_TARGET 0x1000000000000000ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_AFU_CMD 0x0000000000000008ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_GSCSI_CMD 0x0000000000000004ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_WRITE_CMD 0x0000000000000002ULL /* afu_rc 0x21 */ +#define SISL_CTX_CAP_READ_CMD 0x0000000000000001ULL /* afu_rc 0x21 */ + __be64 mbox_r; +}; + +/* single copy global regs */ +struct sisl_global_regs { + __be64 aintr_status; + /* In cxlflash, each FC port/link gets a byte of status */ +#define SISL_ASTATUS_FC0_OTHER 0x8000ULL /* b48, other err, + FC_ERRCAP[31:20] */ +#define SISL_ASTATUS_FC0_LOGO 0x4000ULL /* b49, target sent FLOGI/PLOGI/LOGO + while logged in */ +#define SISL_ASTATUS_FC0_CRC_T 0x2000ULL /* b50, CRC threshold exceeded */ +#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state mechine timed out + and retrying */ +#define SISL_ASTATUS_FC0_LOGI_F 0x0800ULL /* b52, login failed, + FC_ERROR[19:0] */ +#define SISL_ASTATUS_FC0_LOGI_S 0x0400ULL /* b53, login succeeded */ +#define SISL_ASTATUS_FC0_LINK_DN 0x0200ULL /* b54, link online to offline */ +#define SISL_ASTATUS_FC0_LINK_UP 0x0100ULL /* b55, link offline to online */ + +#define SISL_ASTATUS_FC1_OTHER 0x0080ULL /* b56 */ +#define SISL_ASTATUS_FC1_LOGO 0x0040ULL /* b57 */ +#define SISL_ASTATUS_FC1_CRC_T 0x0020ULL /* b58 */ +#define SISL_ASTATUS_FC1_LOGI_R 0x0010ULL /* b59 */ +#define SISL_ASTATUS_FC1_LOGI_F 0x0008ULL /* b60 */ +#define SISL_ASTATUS_FC1_LOGI_S 0x0004ULL /* b61 */ +#define SISL_ASTATUS_FC1_LINK_DN 0x0002ULL /* b62 */ +#define SISL_ASTATUS_FC1_LINK_UP 0x0001ULL /* b63 */ + +#define SISL_FC_INTERNAL_UNMASK 0x0000000300000000ULL /* 1 means unmasked */ +#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK) +#define SISL_FC_INTERNAL_SHIFT 32 + +#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */ +#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */ + + __be64 aintr_clear; + __be64 aintr_mask; + __be64 afu_ctrl; + __be64 afu_hb; + __be64 afu_scratch_pad; + __be64 afu_port_sel; +#define SISL_AFUCONF_AR_IOARCB 0x4000ULL +#define SISL_AFUCONF_AR_LXT 0x2000ULL +#define SISL_AFUCONF_AR_RHT 0x1000ULL +#define SISL_AFUCONF_AR_DATA 0x0800ULL +#define SISL_AFUCONF_AR_RSRC 0x0400ULL +#define SISL_AFUCONF_AR_IOASA 0x0200ULL +#define SISL_AFUCONF_AR_RRQ 0x0100ULL +/* Aggregate all Auto Retry Bits */ +#define SISL_AFUCONF_AR_ALL (SISL_AFUCONF_AR_IOARCB|SISL_AFUCONF_AR_LXT| \ + SISL_AFUCONF_AR_RHT|SISL_AFUCONF_AR_DATA| \ + SISL_AFUCONF_AR_RSRC|SISL_AFUCONF_AR_IOASA| \ + SISL_AFUCONF_AR_RRQ) +#ifdef __BIG_ENDIAN +#define SISL_AFUCONF_ENDIAN 0x0000ULL +#else +#define SISL_AFUCONF_ENDIAN 0x0020ULL +#endif +#define SISL_AFUCONF_MBOX_CLR_READ 0x0010ULL + __be64 afu_config; + __be64 rsvd[0xf8]; + __be64 afu_version; + __be64 interface_version; +}; + +#define CXLFLASH_NUM_FC_PORTS 2 +#define CXLFLASH_MAX_CONTEXT 512 /* how many contexts per afu */ +#define CXLFLASH_NUM_VLUNS 512 + +struct sisl_global_map { + union { + struct sisl_global_regs regs; + char page0[SIZE_4K]; /* page 0 */ + }; + + char page1[SIZE_4K]; /* page 1 */ + + /* pages 2 & 3 */ + __be64 fc_regs[CXLFLASH_NUM_FC_PORTS][CXLFLASH_NUM_VLUNS]; + + /* pages 4 & 5 (lun tbl) */ + __be64 fc_port[CXLFLASH_NUM_FC_PORTS][CXLFLASH_NUM_VLUNS]; + +}; + +/* + * CXL Flash Memory Map + * + * +-------------------------------+ + * | 512 * 64 KB User MMIO | + * | (per context) | + * | User Accessible | + * +-------------------------------+ + * | 512 * 128 B per context | + * | Provisioning and Control | + * | Trusted Process accessible | + * +-------------------------------+ + * | 64 KB Global | + * | Trusted Process accessible | + * +-------------------------------+ +*/ +struct cxlflash_afu_map { + union { + struct sisl_host_map host; + char harea[SIZE_64K]; /* 64KB each */ + } hosts[CXLFLASH_MAX_CONTEXT]; + + union { + struct sisl_ctrl_map ctrl; + char carea[cache_line_size()]; /* 128B each */ + } ctrls[CXLFLASH_MAX_CONTEXT]; + + union { + struct sisl_global_map global; + char garea[SIZE_64K]; /* 64KB single block */ + }; +}; + +/* LBA translation control blocks */ + +struct sisl_lxt_entry { + u64 rlba_base; /* bits 0:47 is base + * b48:55 is lun index + * b58:59 is write & read perms + * (if no perm, afu_rc=0x15) + * b60:63 is port_sel mask + */ + +}; + +/* Per the SISlite spec, RHT entries are to be 16-byte aligned */ +struct sisl_rht_entry { + struct sisl_lxt_entry *lxt_start; + u32 lxt_cnt; + u16 rsvd; + u8 fp; /* format & perm nibbles. + * (if no perm, afu_rc=0x05) + */ + u8 nmask; +} __packed __aligned(16); + +struct sisl_rht_entry_f1 { + u64 lun_id; + union { + struct { + u8 valid; + u8 rsvd[5]; + u8 fp; + u8 port_sel; + }; + + u64 dw; + }; +} __packed __aligned(16); + +/* make the fp byte */ +#define SISL_RHT_FP(fmt, perm) (((fmt) << 4) | (perm)) + +/* make the fp byte for a clone from a source fp and clone flags + * flags must be only 2 LSB bits. + */ +#define SISL_RHT_FP_CLONE(src_fp, cln_flags) ((src_fp) & (0xFC | (cln_flags))) + +#define RHT_PERM_READ 0x01U +#define RHT_PERM_WRITE 0x02U +#define RHT_PERM_RW (RHT_PERM_READ | RHT_PERM_WRITE) + +/* extract the perm bits from a fp */ +#define SISL_RHT_PERM(fp) ((fp) & RHT_PERM_RW) + +#define PORT0 0x01U +#define PORT1 0x02U +#define BOTH_PORTS (PORT0 | PORT1) + +/* AFU Sync Mode byte */ +#define AFU_LW_SYNC 0x0U +#define AFU_HW_SYNC 0x1U +#define AFU_GSYNC 0x2U + +/* Special Task Management Function CDB */ +#define TMF_LUN_RESET 0x1U +#define TMF_CLEAR_ACA 0x2U + +#endif /* _SISLITE_H */ From d8571b1ecbd497d78923e046262872e3206b2deb Mon Sep 17 00:00:00 2001 From: Suresh Thiagarajan Date: Thu, 12 Feb 2015 12:04:37 +0530 Subject: [PATCH 08/85] pm80xx: Added pm8006 controller support Signed-off-by: Suresh Thiagarajan Signed-off-by: Viswas G Acked-by: Jack Wang Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_defs.h | 3 ++- drivers/scsi/pm8001/pm8001_init.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 74a4bb9af07b..dc4233be52c8 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -49,7 +49,8 @@ enum chip_flavors { chip_8019, chip_8074, chip_8076, - chip_8077 + chip_8077, + chip_8006, }; enum phy_speed { diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index a132f2664d2f..5c0356fb6310 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -57,6 +57,7 @@ static const struct pm8001_chip_info pm8001_chips[] = { [chip_8074] = {0, 8, &pm8001_80xx_dispatch,}, [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, + [chip_8006] = {0, 16, &pm8001_80xx_dispatch,}, }; static int pm8001_id; @@ -1107,6 +1108,8 @@ err_out_enable: */ static struct pci_device_id pm8001_pci_table[] = { { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 }, + { PCI_VDEVICE(PMC_Sierra, 0x8006), chip_8006 }, + { PCI_VDEVICE(ADAPTEC2, 0x8006), chip_8006 }, { PCI_VDEVICE(ATTO, 0x0042), chip_8001 }, /* Support for SPC/SPCv/SPCve controllers */ { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 }, @@ -1217,7 +1220,7 @@ MODULE_AUTHOR("Anand Kumar Santhanam "); MODULE_AUTHOR("Sangeetha Gnanasekaran "); MODULE_AUTHOR("Nikith Ganigarakoppal "); MODULE_DESCRIPTION( - "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 " + "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077 " "SAS/SATA controller driver"); MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); From a30c2a3bf8571c6748dd16edc10b32d45ed71a72 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 30 Apr 2015 09:13:05 -0300 Subject: [PATCH 09/85] qla2xxx: prevent board_disable from running during EEH Commit f3ddac1918fe963bcbf8d407a3a3c0881b47248b ("[SCSI] qla2xxx: Disable adapter when we encounter a PCI disconnect.") has introduced a code that disables the board, releasing some resources, when reading 0xffffffff. In case this happens when there is an EEH, this read will trigger EEH detection and set PCI channel offline. EEH will be able to recover the card from this state by doing a reset, so it's a better option than simply disabling the card. Since eeh_check_failure will mark the channel as offline before returning the read value, in case there really was an EEH, we can simply check for pci_channel_offline, preventing the board_disable code from running if it's true. Without this patch, EEH code will try to access those same resources that board_disable will try to free. This race can cause EEH recovery to fail. [ 504.370577] EEH: Notify device driver to resume [ 504.370580] qla2xxx [0001:07:00.0]-9002:2: The device failed to resume I/O from slot/link_reset. Signed-off-by: Thadeu Lima de Souza Cascardo Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5559d5e75bbf..dcfa4655ce43 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -116,7 +116,7 @@ bool qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *vha, uint32_t reg) { /* Check for PCI disconnection */ - if (reg == 0xffffffff) { + if (reg == 0xffffffff && !pci_channel_offline(vha->hw->pdev)) { if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags) && !test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags) && !test_bit(PFLG_DRIVER_PROBING, &vha->pci_flags)) { From 0a66ac17abf2bd03e30fbe20b1847258b960b683 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Fri, 22 May 2015 11:15:02 +0200 Subject: [PATCH 10/85] mvsas: always iounmap resources In case pci_resource_start() or pci_resource_len() reutrn 0, mvsas_ioremap returns without doing an iounmap() of mvi->regs_ex. Found by the cocinelle tool. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index d40d734aa53a..f466a6aa8830 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -338,8 +338,11 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex) res_start = pci_resource_start(pdev, bar); res_len = pci_resource_len(pdev, bar); - if (!res_start || !res_len) + if (!res_start || !res_len) { + iounmap(mvi->regs_ex); + mvi->regs_ex = NULL; goto err_out; + } res_flag = pci_resource_flags(pdev, bar); if (res_flag & IORESOURCE_CACHEABLE) From ce83a4ca18391cfe823629c3863108d265e976f8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 5 Jun 2015 14:20:40 -0700 Subject: [PATCH 11/85] libfc: Fix a typo in a source code comment Signed-off-by: Bart Van Assche Signed-off-by: Vasu Dev Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index c6795941b45d..4cd49d4f44de 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -191,7 +191,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_pkt_destory() - Release hold on a fcp_pkt + * fc_fcp_pkt_destroy() - Release hold on a fcp_pkt * @seq: The sequence that the FCP packet is on (required by destructor API) * @fsp: The FCP packet to be released * From 3ff448b5b7dc7ad4d664588c343da1e5e2ce18dd Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 12 Jun 2015 01:50:45 +0300 Subject: [PATCH 12/85] bfa: fix leak of bfad_im_port_index on module unload Resources allocated within bfad_im_port_index idr are not deallocated on module unload. The patch adds idr_destroy() in exit function. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Reviewed-by: Johannes Thumshirn Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_im.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 7223b0006740..8367c11d554b 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -851,6 +851,8 @@ bfad_im_module_exit(void) if (bfad_im_scsi_vport_transport_template) fc_release_transport(bfad_im_scsi_vport_transport_template); + + idr_destroy(&bfad_im_port_index); } void From 442d75628a3040bbfeb4a1f743b70a8afec0adbc Mon Sep 17 00:00:00 2001 From: "Seymour, Shane M" Date: Tue, 23 Jun 2015 08:11:00 +0000 Subject: [PATCH 13/85] st: convert to using driver attr groups for sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch changes the st driver to use attribute groups so driver sysfs files are created automatically. See the following for reference: http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/ Signed-off-by: Shane Seymour Reviewed-by: Greg Kroah-Hartman Acked-by: Kai Mäkisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 58 ++++++++--------------------------------------- 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 871f3553987d..84e98b982098 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -85,6 +85,7 @@ static int debug_flag; static struct class st_sysfs_class; static const struct attribute_group *st_dev_groups[]; +static const struct attribute_group *st_drv_groups[]; MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI tape (st) driver"); @@ -198,15 +199,13 @@ static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int); static int st_probe(struct device *); static int st_remove(struct device *); -static int do_create_sysfs_files(void); -static void do_remove_sysfs_files(void); - static struct scsi_driver st_template = { .gendrv = { .name = "st", .owner = THIS_MODULE, .probe = st_probe, .remove = st_remove, + .groups = st_drv_groups, }, }; @@ -4404,14 +4403,8 @@ static int __init init_st(void) if (err) goto err_chrdev; - err = do_create_sysfs_files(); - if (err) - goto err_scsidrv; - return 0; -err_scsidrv: - scsi_unregister_driver(&st_template.gendrv); err_chrdev: unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); @@ -4422,7 +4415,6 @@ err_class: static void __exit exit_st(void) { - do_remove_sysfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); @@ -4459,44 +4451,14 @@ static ssize_t st_version_show(struct device_driver *ddd, char *buf) } static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL); -static int do_create_sysfs_files(void) -{ - struct device_driver *sysfs = &st_template.gendrv; - int err; - - err = driver_create_file(sysfs, &driver_attr_try_direct_io); - if (err) - return err; - err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size); - if (err) - goto err_try_direct_io; - err = driver_create_file(sysfs, &driver_attr_max_sg_segs); - if (err) - goto err_attr_fixed_buf; - err = driver_create_file(sysfs, &driver_attr_version); - if (err) - goto err_attr_max_sg; - - return 0; - -err_attr_max_sg: - driver_remove_file(sysfs, &driver_attr_max_sg_segs); -err_attr_fixed_buf: - driver_remove_file(sysfs, &driver_attr_fixed_buffer_size); -err_try_direct_io: - driver_remove_file(sysfs, &driver_attr_try_direct_io); - return err; -} - -static void do_remove_sysfs_files(void) -{ - struct device_driver *sysfs = &st_template.gendrv; - - driver_remove_file(sysfs, &driver_attr_version); - driver_remove_file(sysfs, &driver_attr_max_sg_segs); - driver_remove_file(sysfs, &driver_attr_fixed_buffer_size); - driver_remove_file(sysfs, &driver_attr_try_direct_io); -} +static struct attribute *st_drv_attrs[] = { + &driver_attr_try_direct_io.attr, + &driver_attr_fixed_buffer_size.attr, + &driver_attr_max_sg_segs.attr, + &driver_attr_version.attr, + NULL, +}; +ATTRIBUTE_GROUPS(st_drv); /* The sysfs simple class interface */ static ssize_t From a93429c300483fa2509ae949a7915a01bd0acd20 Mon Sep 17 00:00:00 2001 From: linux Date: Fri, 31 Jul 2015 11:25:55 +0800 Subject: [PATCH 14/85] hptiop: Support HighPoint RR36xx HBAs and Support SAS tape and SAS media changer Support HighPoint RR36xx HBAs which are based on Marvell Frey. Support SAS tape and SAS media changer. [jejb: remove now unused label] Signed-off-by: HighPoint Linux Team Reviewed-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/hptiop.c | 101 ++++++++++++++++++++++++++---------------- drivers/scsi/hptiop.h | 6 +-- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index e995218476ed..a83f705ed8a5 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx/4xxx controller driver for Linux - * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006-2015 HighPoint Technologies, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver"); static char driver_name[] = "hptiop"; static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver"; -static const char driver_ver[] = "v1.8"; +static const char driver_ver[] = "v1.10.0"; static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec); static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, @@ -764,9 +764,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, scsi_set_resid(scp, scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length)); scp->result = SAM_STAT_CHECK_CONDITION; - memcpy(scp->sense_buffer, &req->sg_list, - min_t(size_t, SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(req->dataxfer_length))); + memcpy(scp->sense_buffer, &req->sg_list, SCSI_SENSE_BUFFERSIZE); goto skip_resid; break; @@ -1037,8 +1035,9 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp, scp->result = 0; - if (scp->device->channel || scp->device->lun || - scp->device->id > hba->max_devices) { + if (scp->device->channel || + (scp->device->id > hba->max_devices) || + ((scp->device->id == (hba->max_devices-1)) && scp->device->lun)) { scp->result = DID_BAD_TARGET << 16; free_req(hba, _req); goto cmd_done; @@ -1168,6 +1167,14 @@ static struct device_attribute *hptiop_attrs[] = { NULL }; +static int hptiop_slave_config(struct scsi_device *sdev) +{ + if (sdev->type == TYPE_TAPE) + blk_queue_max_hw_sectors(sdev->request_queue, 8192); + + return 0; +} + static struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = driver_name, @@ -1179,6 +1186,7 @@ static struct scsi_host_template driver_template = { .use_clustering = ENABLE_CLUSTERING, .proc_name = driver_name, .shost_attrs = hptiop_attrs, + .slave_configure = hptiop_slave_config, .this_id = -1, .change_queue_depth = hptiop_adjust_disk_queue_depth, }; @@ -1323,6 +1331,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) } hba = (struct hptiop_hba *)host->hostdata; + memset(hba, 0, sizeof(struct hptiop_hba)); hba->ops = iop_ops; hba->pcidev = pcidev; @@ -1336,7 +1345,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) init_waitqueue_head(&hba->reset_wq); init_waitqueue_head(&hba->ioctl_wq); - host->max_lun = 1; + host->max_lun = 128; host->max_channel = 0; host->io_port = 0; host->n_io_port = 0; @@ -1428,34 +1437,33 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests); hba->req_size = req_size; - start_virt = dma_alloc_coherent(&pcidev->dev, - hba->req_size*hba->max_requests + 0x20, - &start_phy, GFP_KERNEL); - - if (!start_virt) { - printk(KERN_ERR "scsi%d: fail to alloc request mem\n", - hba->host->host_no); - goto free_request_irq; - } - - hba->dma_coherent = start_virt; - hba->dma_coherent_handle = start_phy; - - if ((start_phy & 0x1f) != 0) { - offset = ((start_phy + 0x1f) & ~0x1f) - start_phy; - start_phy += offset; - start_virt += offset; - } - hba->req_list = NULL; + for (i = 0; i < hba->max_requests; i++) { + start_virt = dma_alloc_coherent(&pcidev->dev, + hba->req_size + 0x20, + &start_phy, GFP_KERNEL); + + if (!start_virt) { + printk(KERN_ERR "scsi%d: fail to alloc request mem\n", + hba->host->host_no); + goto free_request_mem; + } + + hba->dma_coherent[i] = start_virt; + hba->dma_coherent_handle[i] = start_phy; + + if ((start_phy & 0x1f) != 0) { + offset = ((start_phy + 0x1f) & ~0x1f) - start_phy; + start_phy += offset; + start_virt += offset; + } + hba->reqs[i].next = NULL; hba->reqs[i].req_virt = start_virt; hba->reqs[i].req_shifted_phy = start_phy >> 5; hba->reqs[i].index = i; free_req(hba, &hba->reqs[i]); - start_virt = (char *)start_virt + hba->req_size; - start_phy = start_phy + hba->req_size; } /* Enable Interrupt and start background task */ @@ -1474,11 +1482,16 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) return 0; free_request_mem: - dma_free_coherent(&hba->pcidev->dev, - hba->req_size * hba->max_requests + 0x20, - hba->dma_coherent, hba->dma_coherent_handle); + for (i = 0; i < hba->max_requests; i++) { + if (hba->dma_coherent[i] && hba->dma_coherent_handle[i]) + dma_free_coherent(&hba->pcidev->dev, + hba->req_size + 0x20, + hba->dma_coherent[i], + hba->dma_coherent_handle[i]); + else + break; + } -free_request_irq: free_irq(hba->pcidev->irq, hba); unmap_pci_bar: @@ -1546,6 +1559,7 @@ static void hptiop_remove(struct pci_dev *pcidev) { struct Scsi_Host *host = pci_get_drvdata(pcidev); struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + u32 i; dprintk("scsi%d: hptiop_remove\n", hba->host->host_no); @@ -1555,10 +1569,15 @@ static void hptiop_remove(struct pci_dev *pcidev) free_irq(hba->pcidev->irq, hba); - dma_free_coherent(&hba->pcidev->dev, - hba->req_size * hba->max_requests + 0x20, - hba->dma_coherent, - hba->dma_coherent_handle); + for (i = 0; i < hba->max_requests; i++) { + if (hba->dma_coherent[i] && hba->dma_coherent_handle[i]) + dma_free_coherent(&hba->pcidev->dev, + hba->req_size + 0x20, + hba->dma_coherent[i], + hba->dma_coherent_handle[i]); + else + break; + } hba->ops->internal_memfree(hba); @@ -1653,6 +1672,14 @@ static struct pci_device_id hptiop_id_table[] = { { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, { PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops }, { PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3610), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3611), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3620), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3622), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3640), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3660), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3680), (kernel_ulong_t)&hptiop_mvfrey_ops }, + { PCI_VDEVICE(TTI, 0x3690), (kernel_ulong_t)&hptiop_mvfrey_ops }, {}, }; diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h index 020619d60b08..4d1c51153b70 100644 --- a/drivers/scsi/hptiop.h +++ b/drivers/scsi/hptiop.h @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx/4xxx controller driver for Linux - * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006-2015 HighPoint Technologies, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -327,8 +327,8 @@ struct hptiop_hba { struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; /* used to free allocated dma area */ - void *dma_coherent; - dma_addr_t dma_coherent_handle; + void *dma_coherent[HPTIOP_MAX_REQUESTS]; + dma_addr_t dma_coherent_handle[HPTIOP_MAX_REQUESTS]; atomic_t reset_count; atomic_t resetting; From 10978e48ccc1718dce5c2d275b761ab99c593a81 Mon Sep 17 00:00:00 2001 From: "Seymour, Shane M" Date: Wed, 24 Jun 2015 06:54:35 +0000 Subject: [PATCH 15/85] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert DRIVER_ATTR macros to DRIVER_ATTR_RO requested by Greg KH. Also switched to using scnprintf instead of snprintf per Documentation/filesystems/sysfs.txt. Suggested-by: Greg Kroah-Hartman Signed-off-by: Shane Seymour Reviewed-by: Hannes Reinecke Reviewed-by: Greg Kroah-Hartman Acked-by: Kai Mäkisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 84e98b982098..9cf3272daa69 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4427,29 +4427,29 @@ module_exit(exit_st); /* The sysfs driver interface. Read-only at the moment */ -static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf) +static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); + return scnprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); } -static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL); +static DRIVER_ATTR_RO(try_direct_io); -static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf) +static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size); + return scnprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size); } -static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL); +static DRIVER_ATTR_RO(fixed_buffer_size); -static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf) +static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs); + return scnprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs); } -static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL); +static DRIVER_ATTR_RO(max_sg_segs); -static ssize_t st_version_show(struct device_driver *ddd, char *buf) +static ssize_t version_show(struct device_driver *ddd, char *buf) { - return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr); + return scnprintf(buf, PAGE_SIZE, "[%s]\n", verstr); } -static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL); +static DRIVER_ATTR_RO(version); static struct attribute *st_drv_attrs[] = { &driver_attr_try_direct_io.attr, From cb1cf0804fe582f8a626c3cc591cb3127536137c Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 25 Jun 2015 18:12:11 +0200 Subject: [PATCH 16/85] storvsc: be more picky about scmnd->sc_data_direction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under the 'default' case in scmnd->sc_data_direction we have 3 options: - DMA_NONE which we handle correctly. - DMA_BIDIRECTIONAL which is never supposed to be set by SCSI stack. - Garbage value. Do WARN() and return -EINVAL in the last two cases. virtio_scsi does BUG_ON() here but it looks like an overkill. Reported-by: Radim Krčmář Signed-off-by: Vitaly Kuznetsov Acked-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3c6584ff65c1..61f485532543 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1598,10 +1598,18 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb->data_in = READ_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; break; - default: + case DMA_NONE: vm_srb->data_in = UNKNOWN_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; break; + default: + /* + * This is DMA_BIDIRECTIONAL or something else we are never + * supposed to see here. + */ + WARN(1, "Unexpected data direction: %d\n", + scmnd->sc_data_direction); + return -EINVAL; } From 8d6a9f5676f0e734967ac3739f5c6a28a0b047d9 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 1 Jul 2015 11:31:27 +0200 Subject: [PATCH 17/85] storvsc: use shost_for_each_device() instead of open coding Comment in struct Scsi_Host says that drivers are not supposed to access __devices directly. storvsc_host_scan() doesn't happen in irq context so we can just use shost_for_each_device(). Signed-off-by: Vitaly Kuznetsov Reviewed-by: Long Li Acked-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 61f485532543..dbc9d9a1c89d 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -426,7 +426,6 @@ static void storvsc_host_scan(struct work_struct *work) struct storvsc_scan_work *wrk; struct Scsi_Host *host; struct scsi_device *sdev; - unsigned long flags; wrk = container_of(work, struct storvsc_scan_work, work); host = wrk->host; @@ -443,14 +442,8 @@ static void storvsc_host_scan(struct work_struct *work) * may have been removed this way. */ mutex_lock(&host->scan_mutex); - spin_lock_irqsave(host->host_lock, flags); - list_for_each_entry(sdev, &host->__devices, siblings) { - spin_unlock_irqrestore(host->host_lock, flags); + shost_for_each_device(sdev, host) scsi_test_unit_ready(sdev, 1, 1, NULL); - spin_lock_irqsave(host->host_lock, flags); - continue; - } - spin_unlock_irqrestore(host->host_lock, flags); mutex_unlock(&host->scan_mutex); /* * Now scan the host to discover LUNs that may have been added. From e819cdb198319cccf4af4fc12ac4d796109d8c23 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 3 Jul 2015 11:53:03 +0300 Subject: [PATCH 18/85] mptfusion: prevent some memory corruption These are signed values the come from the user, we put a cap on the upper bounds but not on the lower bounds. We use "karg.dataSgeOffset" to calculate "sz". We verify "sz" and proceed as if that means that "karg.dataSgeOffset" is correct but this fails to consider that the "sz" calculations can have integer overflows. Signed-off-by: Dan Carpenter Reviewed-by: Johannes Thumshirn Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 70bb7530b22c..fc7393729081 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1859,6 +1859,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) } spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + /* Basic sanity checks to prevent underflows or integer overflows */ + if (karg.maxReplyBytes < 0 || + karg.dataInSize < 0 || + karg.dataOutSize < 0 || + karg.dataSgeOffset < 0 || + karg.maxSenseBytes < 0 || + karg.dataSgeOffset > ioc->req_sz / 4) + return -EINVAL; + /* Verify that the final request frame will not be too large. */ sz = karg.dataSgeOffset * 4; From 14c3e677df9fa2e4bf87b9de683452fc140934b2 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 6 Jul 2015 13:41:53 +0200 Subject: [PATCH 19/85] scsi: Add ALUA state change UA handling Log the ALUA state change unit attention correctly with the message log and emit an event to allow user-space tools to react to it. Signed-off-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Reviewed-by: Bart Van Assche Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 4 ++++ drivers/scsi/scsi_lib.c | 4 ++++ include/scsi/scsi_device.h | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cfadccef045c..d7d28061b31d 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -421,6 +421,10 @@ static void scsi_report_sense(struct scsi_device *sdev, evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED; sdev_printk(KERN_WARNING, sdev, "Mode parameters changed"); + } else if (sshdr->asc == 0x2a && sshdr->ascq == 0x06) { + evt_type = SDEV_EVT_ALUA_STATE_CHANGE_REPORTED; + sdev_printk(KERN_WARNING, sdev, + "Asymmetric access state changed"); } else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) { evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED; sdev_printk(KERN_WARNING, sdev, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dffa91c67f5b..882864f5cbae 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2712,6 +2712,9 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) case SDEV_EVT_LUN_CHANGE_REPORTED: envp[idx++] = "SDEV_UA=REPORTED_LUNS_DATA_HAS_CHANGED"; break; + case SDEV_EVT_ALUA_STATE_CHANGE_REPORTED: + envp[idx++] = "SDEV_UA=ASYMMETRIC_ACCESS_STATE_CHANGED"; + break; default: /* do nothing */ break; @@ -2815,6 +2818,7 @@ struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, case SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED: case SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED: case SDEV_EVT_LUN_CHANGE_REPORTED: + case SDEV_EVT_ALUA_STATE_CHANGE_REPORTED: default: /* do nothing */ break; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index ae84b2214d40..50c2a363bc8f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -57,9 +57,10 @@ enum scsi_device_event { SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED, /* 38 07 UA reported */ SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED, /* 2A 01 UA reported */ SDEV_EVT_LUN_CHANGE_REPORTED, /* 3F 0E UA reported */ + SDEV_EVT_ALUA_STATE_CHANGE_REPORTED, /* 2A 06 UA reported */ SDEV_EVT_FIRST = SDEV_EVT_MEDIA_CHANGE, - SDEV_EVT_LAST = SDEV_EVT_LUN_CHANGE_REPORTED, + SDEV_EVT_LAST = SDEV_EVT_ALUA_STATE_CHANGE_REPORTED, SDEV_EVT_MAXBITS = SDEV_EVT_LAST + 1 }; From 3b8a1ba378b7502c7206ab3da5ea484a132ad30c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 7 Jul 2015 15:52:25 -0500 Subject: [PATCH 20/85] megaraid : use dev_printk when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas Reviewed-by: Hannes Reinecke Acked-by: Sumit Saxena Signed-off-by: James Bottomley --- drivers/scsi/megaraid.c | 140 +++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 74 deletions(-) diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index bc7b34c02723..9d05302a3bcd 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -268,8 +268,8 @@ mega_query_adapter(adapter_t *adapter) raw_mbox[2] = NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */ if ((retval = issue_scb_block(adapter, raw_mbox))) - printk(KERN_WARNING - "megaraid: Product_info cmd failed with error: %d\n", + dev_warn(&adapter->dev->dev, + "Product_info cmd failed with error: %d\n", retval); pci_unmap_single(adapter->dev, prod_info_dma_handle, @@ -334,7 +334,7 @@ mega_query_adapter(adapter_t *adapter) adapter->bios_version[4] = 0; } - printk(KERN_NOTICE "megaraid: [%s:%s] detected %d logical drives.\n", + dev_notice(&adapter->dev->dev, "[%s:%s] detected %d logical drives\n", adapter->fw_version, adapter->bios_version, adapter->numldrv); /* @@ -342,7 +342,7 @@ mega_query_adapter(adapter_t *adapter) */ adapter->support_ext_cdb = mega_support_ext_cdb(adapter); if (adapter->support_ext_cdb) - printk(KERN_NOTICE "megaraid: supports extended CDBs.\n"); + dev_notice(&adapter->dev->dev, "supports extended CDBs\n"); return 0; @@ -678,11 +678,11 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) if(!(adapter->flag & (1L << cmd->device->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning scsi channel %d ", + dev_notice(&adapter->dev->dev, + "scsi%d: scanning scsi channel %d " + "for logical drives\n", adapter->host->host_no, cmd->device->channel); - printk("for logical drives.\n"); adapter->flag |= (1L << cmd->device->channel); } @@ -983,11 +983,11 @@ mega_prepare_passthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd, case READ_CAPACITY: if(!(adapter->flag & (1L << cmd->device->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning scsi channel %d [P%d] ", + dev_notice(&adapter->dev->dev, + "scsi%d: scanning scsi channel %d [P%d] " + "for physical devices\n", adapter->host->host_no, cmd->device->channel, channel); - printk("for physical devices.\n"); adapter->flag |= (1L << cmd->device->channel); } @@ -1045,11 +1045,11 @@ mega_prepare_extpassthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd, case READ_CAPACITY: if(!(adapter->flag & (1L << cmd->device->channel))) { - printk(KERN_NOTICE - "scsi%d: scanning scsi channel %d [P%d] ", + dev_notice(&adapter->dev->dev, + "scsi%d: scanning scsi channel %d [P%d] " + "for physical devices\n", adapter->host->host_no, cmd->device->channel, channel); - printk("for physical devices.\n"); adapter->flag |= (1L << cmd->device->channel); } @@ -1241,7 +1241,7 @@ issue_scb_block(adapter_t *adapter, u_char *raw_mbox) return mbox->m_in.status; bug_blocked_mailbox: - printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n"); + dev_warn(&adapter->dev->dev, "Blocked mailbox......!!\n"); udelay (1000); return -1; } @@ -1454,9 +1454,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) * Make sure f/w has completed a valid command */ if( !(scb->state & SCB_ISSUED) || scb->cmd == NULL ) { - printk(KERN_CRIT - "megaraid: invalid command "); - printk("Id %d, scb->state:%x, scsi cmd:%p\n", + dev_crit(&adapter->dev->dev, "invalid command " + "Id %d, scb->state:%x, scsi cmd:%p\n", cmdid, scb->state, scb->cmd); continue; @@ -1467,8 +1466,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) */ if( scb->state & SCB_ABORT ) { - printk(KERN_WARNING - "megaraid: aborted cmd [%x] complete.\n", + dev_warn(&adapter->dev->dev, + "aborted cmd [%x] complete\n", scb->idx); scb->cmd->result = (DID_ABORT << 16); @@ -1486,8 +1485,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) */ if( scb->state & SCB_RESET ) { - printk(KERN_WARNING - "megaraid: reset cmd [%x] complete.\n", + dev_warn(&adapter->dev->dev, + "reset cmd [%x] complete\n", scb->idx); scb->cmd->result = (DID_RESET << 16); @@ -1553,8 +1552,7 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) if( sg_page(sgl) ) { c = *(unsigned char *) sg_virt(&sgl[0]); } else { - printk(KERN_WARNING - "megaraid: invalid sg.\n"); + dev_warn(&adapter->dev->dev, "invalid sg\n"); c = 0; } @@ -1902,11 +1900,10 @@ megaraid_reset(struct scsi_cmnd *cmd) mc.opcode = MEGA_RESET_RESERVATIONS; if( mega_internal_command(adapter, &mc, NULL) != 0 ) { - printk(KERN_WARNING - "megaraid: reservation reset failed.\n"); + dev_warn(&adapter->dev->dev, "reservation reset failed\n"); } else { - printk(KERN_INFO "megaraid: reservation reset.\n"); + dev_info(&adapter->dev->dev, "reservation reset\n"); } #endif @@ -1939,7 +1936,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) struct list_head *pos, *next; scb_t *scb; - printk(KERN_WARNING "megaraid: %s cmd=%x \n", + dev_warn(&adapter->dev->dev, "%s cmd=%x \n", (aor == SCB_ABORT)? "ABORTING":"RESET", cmd->cmnd[0], cmd->device->channel, cmd->device->id, (u32)cmd->device->lun); @@ -1963,8 +1960,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) */ if( scb->state & SCB_ISSUED ) { - printk(KERN_WARNING - "megaraid: %s[%x], fw owner.\n", + dev_warn(&adapter->dev->dev, + "%s[%x], fw owner\n", (aor==SCB_ABORT) ? "ABORTING":"RESET", scb->idx); @@ -1976,8 +1973,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) * Not yet issued! Remove from the pending * list */ - printk(KERN_WARNING - "megaraid: %s-[%x], driver owner.\n", + dev_warn(&adapter->dev->dev, + "%s-[%x], driver owner\n", (aor==SCB_ABORT) ? "ABORTING":"RESET", scb->idx); @@ -2197,7 +2194,7 @@ proc_show_rebuild_rate(struct seq_file *m, void *v) if( mega_adapinq(adapter, dma_handle) != 0 ) { seq_puts(m, "Adapter inquiry failed.\n"); - printk(KERN_WARNING "megaraid: inquiry failed.\n"); + dev_warn(&adapter->dev->dev, "inquiry failed\n"); goto free_inquiry; } @@ -2241,7 +2238,7 @@ proc_show_battery(struct seq_file *m, void *v) if( mega_adapinq(adapter, dma_handle) != 0 ) { seq_puts(m, "Adapter inquiry failed.\n"); - printk(KERN_WARNING "megaraid: inquiry failed.\n"); + dev_warn(&adapter->dev->dev, "inquiry failed\n"); goto free_inquiry; } @@ -2350,7 +2347,7 @@ proc_show_pdrv(struct seq_file *m, adapter_t *adapter, int channel) if( mega_adapinq(adapter, dma_handle) != 0 ) { seq_puts(m, "Adapter inquiry failed.\n"); - printk(KERN_WARNING "megaraid: inquiry failed.\n"); + dev_warn(&adapter->dev->dev, "inquiry failed\n"); goto free_inquiry; } @@ -2525,7 +2522,7 @@ proc_show_rdrv(struct seq_file *m, adapter_t *adapter, int start, int end ) if( mega_adapinq(adapter, dma_handle) != 0 ) { seq_puts(m, "Adapter inquiry failed.\n"); - printk(KERN_WARNING "megaraid: inquiry failed.\n"); + dev_warn(&adapter->dev->dev, "inquiry failed\n"); goto free_inquiry; } @@ -2799,7 +2796,7 @@ mega_create_proc_entry(int index, struct proc_dir_entry *parent) dir = adapter->controller_proc_dir_entry = proc_mkdir_data(string, 0, parent, adapter); if(!dir) { - printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n"); + dev_warn(&adapter->dev->dev, "proc_mkdir failed\n"); return; } @@ -2807,7 +2804,7 @@ mega_create_proc_entry(int index, struct proc_dir_entry *parent) de = proc_create_data(f->name, S_IRUSR, dir, &mega_proc_fops, f->show); if (!de) { - printk(KERN_WARNING "\nmegaraid: proc_create failed\n"); + dev_warn(&adapter->dev->dev, "proc_create failed\n"); return; } @@ -2874,9 +2871,9 @@ megaraid_biosparam(struct scsi_device *sdev, struct block_device *bdev, return rval; } - printk(KERN_INFO - "megaraid: invalid partition on this disk on channel %d\n", - sdev->channel); + dev_info(&adapter->dev->dev, + "invalid partition on this disk on channel %d\n", + sdev->channel); /* Default heads (64) & sectors (32) */ heads = 64; @@ -2936,7 +2933,7 @@ mega_init_scb(adapter_t *adapter) scb->sgl = (mega_sglist *)scb->sgl64; if( !scb->sgl ) { - printk(KERN_WARNING "RAID: Can't allocate sglist.\n"); + dev_warn(&adapter->dev->dev, "RAID: Can't allocate sglist\n"); mega_free_sgl(adapter); return -1; } @@ -2946,7 +2943,7 @@ mega_init_scb(adapter_t *adapter) &scb->pthru_dma_addr); if( !scb->pthru ) { - printk(KERN_WARNING "RAID: Can't allocate passthru.\n"); + dev_warn(&adapter->dev->dev, "RAID: Can't allocate passthru\n"); mega_free_sgl(adapter); return -1; } @@ -2956,8 +2953,8 @@ mega_init_scb(adapter_t *adapter) &scb->epthru_dma_addr); if( !scb->epthru ) { - printk(KERN_WARNING - "Can't allocate extended passthru.\n"); + dev_warn(&adapter->dev->dev, + "Can't allocate extended passthru\n"); mega_free_sgl(adapter); return -1; } @@ -3154,8 +3151,8 @@ megadev_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) * Do we support this feature */ if( !adapter->support_random_del ) { - printk(KERN_WARNING "megaraid: logdrv "); - printk("delete on non-supporting F/W.\n"); + dev_warn(&adapter->dev->dev, "logdrv " + "delete on non-supporting F/W\n"); return (-EINVAL); } @@ -3179,7 +3176,7 @@ megadev_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU64 || uioc.uioc_rmbox[0] == MEGA_MBOXCMD_EXTPTHRU ) { - printk(KERN_WARNING "megaraid: rejected passthru.\n"); + dev_warn(&adapter->dev->dev, "rejected passthru\n"); return (-EINVAL); } @@ -3683,11 +3680,11 @@ mega_enum_raid_scsi(adapter_t *adapter) for( i = 0; i < adapter->product_info.nchannels; i++ ) { if( (adapter->mega_ch_class >> i) & 0x01 ) { - printk(KERN_INFO "megaraid: channel[%d] is raid.\n", + dev_info(&adapter->dev->dev, "channel[%d] is raid\n", i); } else { - printk(KERN_INFO "megaraid: channel[%d] is scsi.\n", + dev_info(&adapter->dev->dev, "channel[%d] is scsi\n", i); } } @@ -3893,7 +3890,7 @@ mega_do_del_logdrv(adapter_t *adapter, int logdrv) /* log this event */ if(rval) { - printk(KERN_WARNING "megaraid: Delete LD-%d failed.", logdrv); + dev_warn(&adapter->dev->dev, "Delete LD-%d failed", logdrv); return rval; } @@ -4161,7 +4158,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) * this information. */ if (rval && trace_level) { - printk("megaraid: cmd [%x, %x, %x] status:[%x]\n", + dev_info(&adapter->dev->dev, "cmd [%x, %x, %x] status:[%x]\n", mc->cmd, mc->opcode, mc->subopcode, rval); } @@ -4244,11 +4241,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) subsysvid = pdev->subsystem_vendor; subsysid = pdev->subsystem_device; - printk(KERN_NOTICE "megaraid: found 0x%4.04x:0x%4.04x:bus %d:", - id->vendor, id->device, pci_bus); - - printk("slot %d:func %d\n", - PCI_SLOT(pci_dev_func), PCI_FUNC(pci_dev_func)); + dev_notice(&pdev->dev, "found 0x%4.04x:0x%4.04x\n", + id->vendor, id->device); /* Read the base port and IRQ from PCI */ mega_baseport = pci_resource_start(pdev, 0); @@ -4259,14 +4253,13 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) flag |= BOARD_MEMMAP; if (!request_mem_region(mega_baseport, 128, "megaraid")) { - printk(KERN_WARNING "megaraid: mem region busy!\n"); + dev_warn(&pdev->dev, "mem region busy!\n"); goto out_disable_device; } mega_baseport = (unsigned long)ioremap(mega_baseport, 128); if (!mega_baseport) { - printk(KERN_WARNING - "megaraid: could not map hba memory\n"); + dev_warn(&pdev->dev, "could not map hba memory\n"); goto out_release_region; } } else { @@ -4285,7 +4278,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) adapter = (adapter_t *)host->hostdata; memset(adapter, 0, sizeof(adapter_t)); - printk(KERN_NOTICE + dev_notice(&pdev->dev, "scsi%d:Found MegaRAID controller at 0x%lx, IRQ:%d\n", host->host_no, mega_baseport, irq); @@ -4323,21 +4316,20 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) adapter->mega_buffer = pci_alloc_consistent(adapter->dev, MEGA_BUFFER_SIZE, &adapter->buf_dma_handle); if (!adapter->mega_buffer) { - printk(KERN_WARNING "megaraid: out of RAM.\n"); + dev_warn(&pdev->dev, "out of RAM\n"); goto out_host_put; } adapter->scb_list = kmalloc(sizeof(scb_t) * MAX_COMMANDS, GFP_KERNEL); if (!adapter->scb_list) { - printk(KERN_WARNING "megaraid: out of RAM.\n"); + dev_warn(&pdev->dev, "out of RAM\n"); goto out_free_cmd_buffer; } if (request_irq(irq, (adapter->flag & BOARD_MEMMAP) ? megaraid_isr_memmapped : megaraid_isr_iomapped, IRQF_SHARED, "megaraid", adapter)) { - printk(KERN_WARNING - "megaraid: Couldn't register IRQ %d!\n", irq); + dev_warn(&pdev->dev, "Couldn't register IRQ %d!\n", irq); goto out_free_scb_list; } @@ -4357,9 +4349,9 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (!strcmp(adapter->fw_version, "3.00") || !strcmp(adapter->fw_version, "3.01")) { - printk( KERN_WARNING - "megaraid: Your card is a Dell PERC " - "2/SC RAID controller with " + dev_warn(&pdev->dev, + "Your card is a Dell PERC " + "2/SC RAID controller with " "firmware\nmegaraid: 3.00 or 3.01. " "This driver is known to have " "corruption issues\nmegaraid: with " @@ -4390,12 +4382,12 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (!strcmp(adapter->fw_version, "H01.07") || !strcmp(adapter->fw_version, "H01.08") || !strcmp(adapter->fw_version, "H01.09") ) { - printk(KERN_WARNING - "megaraid: Firmware H.01.07, " + dev_warn(&pdev->dev, + "Firmware H.01.07, " "H.01.08, and H.01.09 on 1M/2M " "controllers\n" - "megaraid: do not support 64 bit " - "addressing.\nmegaraid: DISABLING " + "do not support 64 bit " + "addressing.\nDISABLING " "64 bit support.\n"); adapter->flag &= ~BOARD_64BIT; } @@ -4503,8 +4495,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) */ adapter->has_cluster = mega_support_cluster(adapter); if (adapter->has_cluster) { - printk(KERN_NOTICE - "megaraid: Cluster driver, initiator id:%d\n", + dev_notice(&pdev->dev, + "Cluster driver, initiator id:%d\n", adapter->this_id); } #endif @@ -4571,7 +4563,7 @@ __megaraid_shutdown(adapter_t *adapter) issue_scb_block(adapter, raw_mbox); if (atomic_read(&adapter->pend_cmds) > 0) - printk(KERN_WARNING "megaraid: pending commands!!\n"); + dev_warn(&adapter->dev->dev, "pending commands!!\n"); /* * Have a delibrate delay to make sure all the caches are From 1be1825453f6d75ea9c9ea0c8549ca481d94a7ab Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 7 Jul 2015 15:52:34 -0500 Subject: [PATCH 21/85] megaraid_sas: use dev_printk when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas Reviewed-by: Hannes Reinecke Acked-by: Sumit Saxena Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 304 ++++++++++---------- drivers/scsi/megaraid/megaraid_sas_fusion.c | 95 +++--- 2 files changed, 196 insertions(+), 203 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 71b884dae27c..a9bd592fde37 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -216,7 +216,7 @@ struct megasas_cmd *megasas_get_cmd(struct megasas_instance struct megasas_cmd, list); list_del_init(&cmd->list); } else { - printk(KERN_ERR "megasas: Command pool empty!\n"); + dev_err(&instance->pdev->dev, "Command pool empty!\n"); } spin_unlock_irqrestore(&instance->mfi_pool_lock, flags); @@ -370,9 +370,9 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, msleep(1000); /* sleep for 3 secs */ pcidata = 0; pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata); - printk(KERN_NOTICE "pcidata = %x\n", pcidata); + dev_notice(&instance->pdev->dev, "pcidata = %x\n", pcidata); if (pcidata & 0x2) { - printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata); + dev_notice(&instance->pdev->dev, "mfi 1068 offset read=%x\n", pcidata); pcidata &= ~0x2; pci_write_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, pcidata); @@ -383,9 +383,9 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, pcidata = 0; pci_read_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata); - printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata); + dev_notice(&instance->pdev->dev, "1068 offset handshake read=%x\n", pcidata); if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) { - printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata); + dev_notice(&instance->pdev->dev, "1068 offset pcidt=%x\n", pcidata); pcidata = 0; pci_write_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata); @@ -824,7 +824,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, while ( !( HostDiag & DIAG_WRITE_ENABLE) ) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); - printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n", + dev_notice(&instance->pdev->dev, "RESETGEN2: retry=%x, hostdiag=%x\n", retry, HostDiag); if (retry++ >= 100) @@ -832,7 +832,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, } - printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag); + dev_notice(&instance->pdev->dev, "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag); writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset); @@ -842,7 +842,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, while ( ( HostDiag & DIAG_RESET_ADAPTER) ) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); - printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n", + dev_notice(&instance->pdev->dev, "RESET_GEN2: retry=%x, hostdiag=%x\n", retry, HostDiag); if (retry++ >= 1000) @@ -1241,7 +1241,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, &pthru->sgl); if (pthru->sge_count > instance->max_num_sge) { - printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n", + dev_err(&instance->pdev->dev, "DCDB too many SGE NUM=%x\n", pthru->sge_count); return 0; } @@ -1382,7 +1382,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); if (ldio->sge_count > instance->max_num_sge) { - printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n", + dev_err(&instance->pdev->dev, "build_ld_io: sge_count = %x\n", ldio->sge_count); return 0; } @@ -1449,24 +1449,24 @@ megasas_dump_pending_frames(struct megasas_instance *instance) u32 sgcount; u32 max_cmd = instance->max_fw_cmds; - printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); - printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); + dev_err(&instance->pdev->dev, "[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); if (IS_DMA64) - printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); else - printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); - printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: Pending OS cmds in FW : \n",instance->host->host_no); for (i = 0; i < max_cmd; i++) { cmd = instance->cmd_list[i]; if(!cmd->scmd) continue; - printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); + dev_err(&instance->pdev->dev, "[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); if (megasas_cmd_type(cmd->scmd) == READ_WRITE_LDIO) { ldio = (struct megasas_io_frame *)cmd->frame; mfi_sgl = &ldio->sgl; sgcount = ldio->sge_count; - printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x," + dev_err(&instance->pdev->dev, "[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x," " lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n", instance->host->host_no, cmd->frame_count, ldio->cmd, ldio->target_id, le32_to_cpu(ldio->start_lba_lo), le32_to_cpu(ldio->start_lba_hi), @@ -1476,7 +1476,7 @@ megasas_dump_pending_frames(struct megasas_instance *instance) pthru = (struct megasas_pthru_frame *) cmd->frame; mfi_sgl = &pthru->sgl; sgcount = pthru->sge_count; - printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, " + dev_err(&instance->pdev->dev, "[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, " "lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n", instance->host->host_no, cmd->frame_count, pthru->cmd, pthru->target_id, pthru->lun, pthru->cdb_len, le32_to_cpu(pthru->data_xfer_len), @@ -1485,27 +1485,26 @@ megasas_dump_pending_frames(struct megasas_instance *instance) if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ for (n = 0; n < sgcount; n++){ if (IS_DMA64) - printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%llx ", + dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%llx\n", le32_to_cpu(mfi_sgl->sge64[n].length), le64_to_cpu(mfi_sgl->sge64[n].phys_addr)); else - printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ", + dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%x\n", le32_to_cpu(mfi_sgl->sge32[n].length), le32_to_cpu(mfi_sgl->sge32[n].phys_addr)); } } - printk(KERN_ERR "\n"); } /*for max_cmd*/ - printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); for (i = 0; i < max_cmd; i++) { cmd = instance->cmd_list[i]; if(cmd->sync_cmd == 1){ - printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); + dev_err(&instance->pdev->dev, "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); } } - printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); + dev_err(&instance->pdev->dev, "[%d]: Dumping Done\n\n",instance->host->host_no); } u32 @@ -1623,7 +1622,7 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) } if (instance->instancet->build_and_issue_cmd(instance, scmd)) { - printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n"); + dev_err(&instance->pdev->dev, "Err returned from build_and_issue_cmd\n"); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1794,7 +1793,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) while (consumer != producer) { context = le32_to_cpu(instance->reply_queue[consumer]); if (context >= instance->max_fw_cmds) { - printk(KERN_ERR "Unexpected context value %x\n", + dev_err(&instance->pdev->dev, "Unexpected context value %x\n", context); BUG(); } @@ -1873,8 +1872,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: megasas_get_ld_vf_affiliation_111:" - "Failed to get cmd for scsi%d.\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "megasas_get_ld_vf_affiliation_111:" + "Failed to get cmd for scsi%d\n", instance->host->host_no); return -ENOMEM; } @@ -1882,8 +1881,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, dcmd = &cmd->frame->dcmd; if (!instance->vf_affiliation_111) { - printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF " - "affiliation for scsi%d.\n", instance->host->host_no); + dev_warn(&instance->pdev->dev, "SR-IOV: Couldn't get LD/VF " + "affiliation for scsi%d\n", instance->host->host_no); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -1897,8 +1896,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, sizeof(struct MR_LD_VF_AFFILIATION_111), &new_affiliation_111_h); if (!new_affiliation_111) { - printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate " - "memory for new affiliation for scsi%d.\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate " + "memory for new affiliation for scsi%d\n", instance->host->host_no); megasas_return_cmd(instance, cmd); return -ENOMEM; @@ -1929,14 +1928,14 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, dcmd->sgl.sge32[0].length = cpu_to_le32( sizeof(struct MR_LD_VF_AFFILIATION_111)); - printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for " + dev_warn(&instance->pdev->dev, "SR-IOV: Getting LD/VF affiliation for " "scsi%d\n", instance->host->host_no); megasas_issue_blocked_cmd(instance, cmd, 0); if (dcmd->cmd_status) { - printk(KERN_WARNING "megasas: SR-IOV: LD/VF affiliation DCMD" - " failed with status 0x%x for scsi%d.\n", + dev_warn(&instance->pdev->dev, "SR-IOV: LD/VF affiliation DCMD" + " failed with status 0x%x for scsi%d\n", dcmd->cmd_status, instance->host->host_no); retval = 1; /* Do a scan if we couldn't get affiliation */ goto out; @@ -1947,9 +1946,8 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, for (ld = 0 ; ld < new_affiliation_111->vdCount; ld++) if (instance->vf_affiliation_111->map[ld].policy[thisVf] != new_affiliation_111->map[ld].policy[thisVf]) { - printk(KERN_WARNING "megasas: SR-IOV: " - "Got new LD/VF affiliation " - "for scsi%d.\n", + dev_warn(&instance->pdev->dev, "SR-IOV: " + "Got new LD/VF affiliation for scsi%d\n", instance->host->host_no); memcpy(instance->vf_affiliation_111, new_affiliation_111, @@ -1985,8 +1983,8 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: megasas_get_ld_vf_affiliation12: " - "Failed to get cmd for scsi%d.\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "megasas_get_ld_vf_affiliation12: " + "Failed to get cmd for scsi%d\n", instance->host->host_no); return -ENOMEM; } @@ -1994,8 +1992,8 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, dcmd = &cmd->frame->dcmd; if (!instance->vf_affiliation) { - printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF " - "affiliation for scsi%d.\n", instance->host->host_no); + dev_warn(&instance->pdev->dev, "SR-IOV: Couldn't get LD/VF " + "affiliation for scsi%d\n", instance->host->host_no); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -2010,8 +2008,8 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, sizeof(struct MR_LD_VF_AFFILIATION), &new_affiliation_h); if (!new_affiliation) { - printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate " - "memory for new affiliation for scsi%d.\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate " + "memory for new affiliation for scsi%d\n", instance->host->host_no); megasas_return_cmd(instance, cmd); return -ENOMEM; @@ -2042,14 +2040,14 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, dcmd->sgl.sge32[0].length = cpu_to_le32((MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION)); - printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for " + dev_warn(&instance->pdev->dev, "SR-IOV: Getting LD/VF affiliation for " "scsi%d\n", instance->host->host_no); megasas_issue_blocked_cmd(instance, cmd, 0); if (dcmd->cmd_status) { - printk(KERN_WARNING "megasas: SR-IOV: LD/VF affiliation DCMD" - " failed with status 0x%x for scsi%d.\n", + dev_warn(&instance->pdev->dev, "SR-IOV: LD/VF affiliation DCMD" + " failed with status 0x%x for scsi%d\n", dcmd->cmd_status, instance->host->host_no); retval = 1; /* Do a scan if we couldn't get affiliation */ goto out; @@ -2057,8 +2055,8 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, if (!initial) { if (!new_affiliation->ldCount) { - printk(KERN_WARNING "megasas: SR-IOV: Got new LD/VF " - "affiliation for passive path for scsi%d.\n", + dev_warn(&instance->pdev->dev, "SR-IOV: Got new LD/VF " + "affiliation for passive path for scsi%d\n", instance->host->host_no); retval = 1; goto out; @@ -2123,8 +2121,8 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, } out: if (doscan) { - printk(KERN_WARNING "megasas: SR-IOV: Got new LD/VF " - "affiliation for scsi%d.\n", instance->host->host_no); + dev_warn(&instance->pdev->dev, "SR-IOV: Got new LD/VF " + "affiliation for scsi%d\n", instance->host->host_no); memcpy(instance->vf_affiliation, new_affiliation, new_affiliation->size); retval = 1; @@ -2164,8 +2162,8 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: megasas_sriov_start_heartbeat: " - "Failed to get cmd for scsi%d.\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "megasas_sriov_start_heartbeat: " + "Failed to get cmd for scsi%d\n", instance->host->host_no); return -ENOMEM; } @@ -2178,9 +2176,9 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, sizeof(struct MR_CTRL_HB_HOST_MEM), &instance->hb_host_mem_h); if (!instance->hb_host_mem) { - printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate" - " memory for heartbeat host memory for " - "scsi%d.\n", instance->host->host_no); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate" + " memory for heartbeat host memory for scsi%d\n", + instance->host->host_no); retval = -ENOMEM; goto out; } @@ -2200,7 +2198,7 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->hb_host_mem_h); dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_CTRL_HB_HOST_MEM)); - printk(KERN_WARNING "megasas: SR-IOV: Starting heartbeat for scsi%d\n", + dev_warn(&instance->pdev->dev, "SR-IOV: Starting heartbeat for scsi%d\n", instance->host->host_no); if (instance->ctrl_context && !instance->mask_interrupts) @@ -2236,7 +2234,7 @@ void megasas_sriov_heartbeat_handler(unsigned long instance_addr) mod_timer(&instance->sriov_heartbeat_timer, jiffies + MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); } else { - printk(KERN_WARNING "megasas: SR-IOV: Heartbeat never " + dev_warn(&instance->pdev->dev, "SR-IOV: Heartbeat never " "completed for scsi%d\n", instance->host->host_no); schedule_work(&instance->work_init); } @@ -2274,7 +2272,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) &clist_local); spin_unlock_irqrestore(&instance->hba_lock, flags); - printk(KERN_NOTICE "megasas: HBA reset wait ...\n"); + dev_notice(&instance->pdev->dev, "HBA reset wait ...\n"); for (i = 0; i < wait_time; i++) { msleep(1000); spin_lock_irqsave(&instance->hba_lock, flags); @@ -2285,7 +2283,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) } if (adprecovery != MEGASAS_HBA_OPERATIONAL) { - printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n"); + dev_notice(&instance->pdev->dev, "reset: Stopping HBA.\n"); spin_lock_irqsave(&instance->hba_lock, flags); instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; spin_unlock_irqrestore(&instance->hba_lock, flags); @@ -2299,14 +2297,14 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) list_del_init(&reset_cmd->list); if (reset_cmd->scmd) { reset_cmd->scmd->result = DID_RESET << 16; - printk(KERN_NOTICE "%d:%p reset [%02x]\n", + dev_notice(&instance->pdev->dev, "%d:%p reset [%02x]\n", reset_index, reset_cmd, reset_cmd->scmd->cmnd[0]); reset_cmd->scmd->scsi_done(reset_cmd->scmd); megasas_return_cmd(instance, reset_cmd); } else if (reset_cmd->sync_cmd) { - printk(KERN_NOTICE "megasas:%p synch cmds" + dev_notice(&instance->pdev->dev, "%p synch cmds" "reset queue\n", reset_cmd); @@ -2315,7 +2313,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) reset_cmd->frame_phys_addr, 0, instance->reg_set); } else { - printk(KERN_NOTICE "megasas: %p unexpected" + dev_notice(&instance->pdev->dev, "%p unexpected" "cmds lst\n", reset_cmd); } @@ -2333,7 +2331,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) break; if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + dev_notice(&instance->pdev->dev, "[%2d]waiting for %d " "commands to complete\n",i,outstanding); /* * Call cmd completion routine. Cmd to be @@ -2384,7 +2382,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) if (atomic_read(&instance->fw_outstanding) || (kill_adapter_flag == 2)) { - printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n"); + dev_notice(&instance->pdev->dev, "pending cmds after reset\n"); /* * Send signal to FW to stop processing any pending cmds. * The controller will be taken offline by the OS now. @@ -2406,7 +2404,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) return FAILED; } - printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n"); + dev_notice(&instance->pdev->dev, "no pending cmds after reset\n"); return SUCCESS; } @@ -2430,16 +2428,15 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd) scmd->cmnd[0], scmd->retries); if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - printk(KERN_ERR "megasas: cannot recover from previous reset " - "failures\n"); + dev_err(&instance->pdev->dev, "cannot recover from previous reset failures\n"); return FAILED; } ret_val = megasas_wait_for_outstanding(instance); if (ret_val == SUCCESS) - printk(KERN_NOTICE "megasas: reset successful \n"); + dev_notice(&instance->pdev->dev, "reset successful\n"); else - printk(KERN_ERR "megasas: failed to do reset\n"); + dev_err(&instance->pdev->dev, "failed to do reset\n"); return ret_val; } @@ -2597,7 +2594,7 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) struct megasas_aen_event *ev; ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(KERN_ERR "megasas_service_aen: out of memory\n"); + dev_err(&instance->pdev->dev, "megasas_service_aen: out of memory\n"); } else { ev->instance = instance; instance->ev = ev; @@ -2847,10 +2844,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, MR_DCMD_CTRL_EVENT_GET_INFO left over from the main kernel when booting the kdump kernel. Ignore this command to prevent a kernel panic on shutdown of the kdump kernel. */ - printk(KERN_WARNING "megaraid_sas: MFI_CMD_INVALID command " - "completed.\n"); - printk(KERN_WARNING "megaraid_sas: If you have a controller " - "other than PERC5, please upgrade your firmware.\n"); + dev_warn(&instance->pdev->dev, "MFI_CMD_INVALID command " + "completed\n"); + dev_warn(&instance->pdev->dev, "If you have a controller " + "other than PERC5, please upgrade your firmware\n"); break; case MFI_CMD_PD_SCSI_IO: case MFI_CMD_LD_SCSI_IO: @@ -2918,7 +2915,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, break; default: - printk(KERN_DEBUG "megasas: MFI FW status %#x\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "MFI FW status %#x\n", hdr->cmd_status); cmd->scmd->result = DID_ERROR << 16; break; @@ -2944,8 +2941,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, if (cmd->frame->hdr.cmd_status != 0) { if (cmd->frame->hdr.cmd_status != MFI_STAT_NOT_FOUND) - printk(KERN_WARNING "megasas: map sync" - "failed, status = 0x%x.\n", + dev_warn(&instance->pdev->dev, "map syncfailed, status = 0x%x\n", cmd->frame->hdr.cmd_status); else { megasas_return_cmd(instance, cmd); @@ -2997,7 +2993,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, break; default: - printk("megasas: Unknown command completed! [0x%X]\n", + dev_info(&instance->pdev->dev, "Unknown command completed! [0x%X]\n", hdr->cmd); break; } @@ -3028,14 +3024,14 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) list_del_init(&cmd->list); if (cmd->sync_cmd || cmd->scmd) { - printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d" - "detected to be pending while HBA reset.\n", + dev_notice(&instance->pdev->dev, "command %p, %p:%d" + "detected to be pending while HBA reset\n", cmd, cmd->scmd, cmd->sync_cmd); cmd->retry_for_fw_reset++; if (cmd->retry_for_fw_reset == 3) { - printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d" + dev_notice(&instance->pdev->dev, "cmd %p, %p:%d" "was tried multiple times during reset." "Shutting down the HBA\n", cmd, cmd->scmd, cmd->sync_cmd); @@ -3048,10 +3044,10 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) if (cmd->sync_cmd == 1) { if (cmd->scmd) { - printk(KERN_NOTICE "megaraid_sas: unexpected" + dev_notice(&instance->pdev->dev, "unexpected" "cmd attached to internal command!\n"); } - printk(KERN_NOTICE "megasas: %p synchronous cmd" + dev_notice(&instance->pdev->dev, "%p synchronous cmd" "on the internal reset queue," "issue it again.\n", cmd); cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; @@ -3059,7 +3055,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) cmd->frame_phys_addr , 0, instance->reg_set); } else if (cmd->scmd) { - printk(KERN_NOTICE "megasas: %p scsi cmd [%02x]" + dev_notice(&instance->pdev->dev, "%p scsi cmd [%02x]" "detected on the internal queue, issue again.\n", cmd, cmd->scmd->cmnd[0]); @@ -3068,14 +3064,14 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) cmd->frame_phys_addr, cmd->frame_count-1, instance->reg_set); } else { - printk(KERN_NOTICE "megasas: %p unexpected cmd on the" + dev_notice(&instance->pdev->dev, "%p unexpected cmd on the" "internal reset defer list while re-issue!!\n", cmd); } } if (instance->aen_cmd) { - printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n"); + dev_notice(&instance->pdev->dev, "aen_cmd in def process\n"); megasas_return_cmd(instance, instance->aen_cmd); instance->aen_cmd = NULL; @@ -3115,12 +3111,12 @@ megasas_internal_reset_defer_cmds(struct megasas_instance *instance) for (i = 0; i < max_cmd; i++) { cmd = instance->cmd_list[i]; if (cmd->sync_cmd == 1 || cmd->scmd) { - printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p" + dev_notice(&instance->pdev->dev, "moving cmd[%d]:%p:%d:%p" "on the defer queue as internal\n", defer_index, cmd, cmd->sync_cmd, cmd->scmd); if (!list_empty(&cmd->list)) { - printk(KERN_NOTICE "megaraid_sas: ERROR while" + dev_notice(&instance->pdev->dev, "ERROR while" " moving this cmd:%p, %d %p, it was" "discovered on some list?\n", cmd, cmd->sync_cmd, cmd->scmd); @@ -3145,13 +3141,13 @@ process_fw_state_change_wq(struct work_struct *work) unsigned long flags; if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) { - printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n", + dev_notice(&instance->pdev->dev, "error, recovery st %x\n", instance->adprecovery); return ; } if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) { - printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" + dev_notice(&instance->pdev->dev, "FW detected to be in fault" "state, restarting it...\n"); instance->instancet->disable_intr(instance); @@ -3161,10 +3157,10 @@ process_fw_state_change_wq(struct work_struct *work) instance->instancet->adp_reset(instance, instance->reg_set); atomic_set(&instance->fw_reset_no_pci_access, 0 ); - printk(KERN_NOTICE "megaraid_sas: FW restarted successfully," + dev_notice(&instance->pdev->dev, "FW restarted successfully," "initiating next stage...\n"); - printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine," + dev_notice(&instance->pdev->dev, "HBA recovery state machine," "state 2 starting...\n"); /*waitting for about 20 second before start the second init*/ @@ -3173,7 +3169,7 @@ process_fw_state_change_wq(struct work_struct *work) } if (megasas_transition_to_ready(instance, 1)) { - printk(KERN_NOTICE "megaraid_sas:adapter not ready\n"); + dev_notice(&instance->pdev->dev, "adapter not ready\n"); atomic_set(&instance->fw_reset_no_pci_access, 1); megaraid_sas_kill_hba(instance); @@ -3238,13 +3234,13 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, instance->reg_set) & MFI_STATE_MASK; if (fw_state != MFI_STATE_FAULT) { - printk(KERN_NOTICE "megaraid_sas: fw state:%x\n", + dev_notice(&instance->pdev->dev, "fw state:%x\n", fw_state); } if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)) { - printk(KERN_NOTICE "megaraid_sas: wait adp restart\n"); + dev_notice(&instance->pdev->dev, "wait adp restart\n"); if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) || @@ -3265,14 +3261,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, atomic_set(&instance->fw_outstanding, 0); megasas_internal_reset_defer_cmds(instance); - printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n", + dev_notice(&instance->pdev->dev, "fwState=%x, stage:%d\n", fw_state, instance->adprecovery); schedule_work(&instance->work_init); return IRQ_HANDLED; } else { - printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n", + dev_notice(&instance->pdev->dev, "fwstate:%x, dis_OCR=%x\n", fw_state, instance->disableOnlineCtrlReset); } } @@ -3322,7 +3318,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) fw_state = abs_state & MFI_STATE_MASK; if (fw_state != MFI_STATE_READY) - printk(KERN_INFO "megasas: Waiting for FW to come to ready" + dev_info(&instance->pdev->dev, "Waiting for FW to come to ready" " state\n"); while (fw_state != MFI_STATE_READY) { @@ -3330,7 +3326,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) switch (fw_state) { case MFI_STATE_FAULT: - printk(KERN_DEBUG "megasas: FW in FAULT state!!\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "FW in FAULT state!!\n"); if (ocr) { max_wait = MEGASAS_RESET_WAIT_TIME; cur_state = MFI_STATE_FAULT; @@ -3469,7 +3465,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) break; default: - printk(KERN_DEBUG "megasas: Unknown state 0x%x\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Unknown state 0x%x\n", fw_state); return -ENODEV; } @@ -3491,7 +3487,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) * Return error if fw_state hasn't changed after max_wait */ if (curr_abs_state == abs_state) { - printk(KERN_DEBUG "FW state [%d] hasn't changed " + dev_printk(KERN_DEBUG, &instance->pdev->dev, "FW state [%d] hasn't changed " "in %d secs\n", fw_state, max_wait); return -ENODEV; } @@ -3499,7 +3495,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) abs_state = curr_abs_state; fw_state = curr_abs_state & MFI_STATE_MASK; } - printk(KERN_INFO "megasas: FW now in Ready state\n"); + dev_info(&instance->pdev->dev, "FW now in Ready state\n"); return 0; } @@ -3594,7 +3590,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) instance->pdev, total_sz, 256, 0); if (!instance->frame_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup frame pool\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup frame pool\n"); return -ENOMEM; } @@ -3602,7 +3598,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) instance->pdev, 128, 4, 0); if (!instance->sense_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup sense pool\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup sense pool\n"); pci_pool_destroy(instance->frame_dma_pool); instance->frame_dma_pool = NULL; @@ -3630,7 +3626,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) * whatever has been allocated */ if (!cmd->frame || !cmd->sense) { - printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "pci_pool_alloc failed\n"); megasas_teardown_frame_pool(instance); return -ENOMEM; } @@ -3708,7 +3704,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL); if (!instance->cmd_list) { - printk(KERN_DEBUG "megasas: out of memory\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "out of memory\n"); return -ENOMEM; } @@ -3744,7 +3740,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) * Create a frame pool and assign one frame to each cmd */ if (megasas_create_frame_pool(instance)) { - printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Error creating frame DMA pool\n"); megasas_free_cmds(instance); } @@ -3773,7 +3769,7 @@ megasas_get_pd_list(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "(get_pd_list): Failed to get cmd\n"); return -ENOMEM; } @@ -3783,7 +3779,7 @@ megasas_get_pd_list(struct megasas_instance *instance) MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for pd_list\n"); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -3868,7 +3864,7 @@ megasas_get_ld_list(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "megasas_get_ld_list: Failed to get cmd\n"); return -ENOMEM; } @@ -3879,7 +3875,7 @@ megasas_get_ld_list(struct megasas_instance *instance) &ci_h); if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem in get_ld_list\n"); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -3954,8 +3950,8 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_WARNING - "megasas:(megasas_ld_list_query): Failed to get cmd\n"); + dev_warn(&instance->pdev->dev, + "megasas_ld_list_query: Failed to get cmd\n"); return -ENOMEM; } @@ -3965,8 +3961,8 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) sizeof(struct MR_LD_TARGETID_LIST), &ci_h); if (!ci) { - printk(KERN_WARNING - "megasas: Failed to alloc mem for ld_list_query\n"); + dev_warn(&instance->pdev->dev, + "Failed to alloc mem for ld_list_query\n"); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -4093,7 +4089,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get a free cmd\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get a free cmd\n"); return -ENOMEM; } @@ -4103,7 +4099,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance) sizeof(struct megasas_ctrl_info), &ci_h); if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for ctrl info\n"); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -4269,7 +4265,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance) */ if (megasas_issue_polled(instance, cmd)) { - printk(KERN_ERR "megasas: Failed to init firmware\n"); + dev_err(&instance->pdev->dev, "Failed to init firmware\n"); megasas_return_cmd(instance, cmd); goto fail_fw_init; } @@ -4342,7 +4338,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance) &instance->reply_queue_h); if (!instance->reply_queue) { - printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Out of DMA mem for reply queue\n"); goto fail_reply_queue; } @@ -4361,7 +4357,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance) (instance->instancet->read_fw_status_reg(reg_set) & 0x04000000); - printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d", + dev_notice(&instance->pdev->dev, "megasas_init_mfi: fw_support_ieee=%d", instance->fw_support_ieee); if (instance->fw_support_ieee) @@ -4505,7 +4501,7 @@ static int megasas_init_fw(struct megasas_instance *instance) instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); if (pci_request_selected_regions(instance->pdev, instance->bar, "megasas: LSI")) { - printk(KERN_DEBUG "megasas: IO memory region busy!\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "IO memory region busy!\n"); return -EBUSY; } @@ -4513,7 +4509,7 @@ static int megasas_init_fw(struct megasas_instance *instance) instance->reg_set = ioremap_nocache(base_addr, 8192); if (!instance->reg_set) { - printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to map IO mem\n"); goto fail_ioremap; } @@ -4551,7 +4547,7 @@ static int megasas_init_fw(struct megasas_instance *instance) (instance, instance->reg_set); atomic_set(&instance->fw_reset_no_pci_access, 0); dev_info(&instance->pdev->dev, - "megasas: FW restarted successfully from %s!\n", + "FW restarted successfully from %s!\n", __func__); /*waitting for about 30 second before retry*/ @@ -4652,7 +4648,7 @@ static int megasas_init_fw(struct megasas_instance *instance) instance->instancet->enable_intr(instance); - printk(KERN_ERR "megasas: INIT adapter done\n"); + dev_err(&instance->pdev->dev, "INIT adapter done\n"); /** for passthrough * the following function will get the PD LIST. @@ -4661,7 +4657,7 @@ static int megasas_init_fw(struct megasas_instance *instance) memset(instance->pd_list, 0 , (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); if (megasas_get_pd_list(instance) < 0) { - printk(KERN_ERR "megasas: failed to get PD list\n"); + dev_err(&instance->pdev->dev, "failed to get PD list\n"); goto fail_get_pd_list; } @@ -4960,7 +4956,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, aen_cmd, 30); if (ret_val) { - printk(KERN_DEBUG "megasas: Failed to abort " + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to abort " "previous AEN command\n"); return ret_val; } @@ -5079,7 +5075,7 @@ static int megasas_io_attach(struct megasas_instance *instance) (max_sectors <= MEGASAS_MAX_SECTORS)) { instance->max_sectors_per_req = max_sectors; } else { - printk(KERN_INFO "megasas: max_sectors should be > 0" + dev_info(&instance->pdev->dev, "max_sectors should be > 0" "and <= %d (or < 1MB for GEN2 controller)\n", instance->max_sectors_per_req); } @@ -5206,7 +5202,7 @@ static int megasas_probe_one(struct pci_dev *pdev, sizeof(struct megasas_instance)); if (!host) { - printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "scsi_host_alloc failed\n"); goto fail_alloc_instance; } @@ -5226,7 +5222,7 @@ static int megasas_probe_one(struct pci_dev *pdev, instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL, instance->ctrl_context_pages); if (!instance->ctrl_context) { - printk(KERN_DEBUG "megasas: Failed to allocate " + dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate " "memory for Fusion context info\n"); goto fail_alloc_dma_buf; } @@ -5245,7 +5241,7 @@ static int megasas_probe_one(struct pci_dev *pdev, &instance->consumer_h); if (!instance->producer || !instance->consumer) { - printk(KERN_DEBUG "megasas: Failed to allocate" + dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate" "memory for producer, consumer\n"); goto fail_alloc_dma_buf; } @@ -5276,7 +5272,7 @@ static int megasas_probe_one(struct pci_dev *pdev, CRASH_DMA_BUF_SIZE, &instance->crash_dump_h); if (!instance->crash_dump_buf) - dev_err(&instance->pdev->dev, "Can't allocate Firmware " + dev_err(&pdev->dev, "Can't allocate Firmware " "crash dump DMA buffer\n"); megasas_poll_wait_aen = 0; @@ -5292,7 +5288,7 @@ static int megasas_probe_one(struct pci_dev *pdev, &instance->evt_detail_h); if (!instance->evt_detail) { - printk(KERN_DEBUG "megasas: Failed to allocate memory for " + dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate memory for " "event detail structure\n"); goto fail_alloc_dma_buf; } @@ -5356,7 +5352,7 @@ static int megasas_probe_one(struct pci_dev *pdev, pci_alloc_consistent(pdev, sizeof(struct MR_LD_VF_AFFILIATION_111), &instance->vf_affiliation_111_h); if (!instance->vf_affiliation_111) - printk(KERN_WARNING "megasas: Can't allocate " + dev_warn(&pdev->dev, "Can't allocate " "memory for VF affiliation buffer\n"); } else { instance->vf_affiliation = @@ -5365,7 +5361,7 @@ static int megasas_probe_one(struct pci_dev *pdev, sizeof(struct MR_LD_VF_AFFILIATION), &instance->vf_affiliation_h); if (!instance->vf_affiliation) - printk(KERN_WARNING "megasas: Can't allocate " + dev_warn(&pdev->dev, "Can't allocate " "memory for VF affiliation buffer\n"); } } @@ -5399,7 +5395,7 @@ static int megasas_probe_one(struct pci_dev *pdev, * Initiate AEN (Asynchronous Event Notification) */ if (megasas_start_aen(instance)) { - printk(KERN_DEBUG "megasas: start aen failed\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "start aen failed\n"); goto fail_start_aen; } @@ -5607,7 +5603,7 @@ megasas_resume(struct pci_dev *pdev) rval = pci_enable_device_mem(pdev); if (rval) { - printk(KERN_ERR "megasas: Enable device failed\n"); + dev_err(&pdev->dev, "Enable device failed\n"); return rval; } @@ -5686,7 +5682,7 @@ megasas_resume(struct pci_dev *pdev) * Initiate AEN (Asynchronous Event Notification) */ if (megasas_start_aen(instance)) - printk(KERN_ERR "megasas: Start AEN failed\n"); + dev_err(&instance->pdev->dev, "Start AEN failed\n"); return 0; @@ -5982,14 +5978,14 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, memset(kbuff_arr, 0, sizeof(kbuff_arr)); if (ioc->sge_count > MAX_IOCTL_SGE) { - printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n", + dev_printk(KERN_DEBUG, &instance->pdev->dev, "SGE count [%d] > max limit [%d]\n", ioc->sge_count, MAX_IOCTL_SGE); return -EINVAL; } cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get a cmd packet\n"); return -ENOMEM; } @@ -6034,8 +6030,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, ioc->sgl[i].iov_len, &buf_handle, GFP_KERNEL); if (!kbuff_arr[i]) { - printk(KERN_DEBUG "megasas: Failed to alloc " - "kernel SGL buffer for IOCTL \n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc " + "kernel SGL buffer for IOCTL\n"); error = -ENOMEM; goto out; } @@ -6108,7 +6104,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), sense, ioc->sense_len)) { - printk(KERN_ERR "megasas: Failed to copy out to user " + dev_err(&instance->pdev->dev, "Failed to copy out to user " "sense data\n"); error = -EFAULT; goto out; @@ -6120,7 +6116,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, */ if (copy_to_user(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status, sizeof(u8))) { - printk(KERN_DEBUG "megasas: Error copying out cmd_status\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Error copying out cmd_status\n"); error = -EFAULT; } @@ -6180,7 +6176,7 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) } if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - printk(KERN_ERR "Controller in crit error\n"); + dev_err(&instance->pdev->dev, "Controller in crit error\n"); error = -ENODEV; goto out_kfree_ioc; } @@ -6205,7 +6201,7 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) spin_unlock_irqrestore(&instance->hba_lock, flags); if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: waiting" + dev_notice(&instance->pdev->dev, "waiting" "for controller reset to finish\n"); } @@ -6216,7 +6212,7 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { spin_unlock_irqrestore(&instance->hba_lock, flags); - printk(KERN_ERR "megaraid_sas: timed out while" + dev_err(&instance->pdev->dev, "timed out while" "waiting for HBA to recover\n"); error = -ENODEV; goto out_up; @@ -6275,7 +6271,7 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) spin_unlock_irqrestore(&instance->hba_lock, flags); if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: waiting for" + dev_notice(&instance->pdev->dev, "waiting for" "controller reset to finish\n"); } @@ -6285,8 +6281,8 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) spin_lock_irqsave(&instance->hba_lock, flags); if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { spin_unlock_irqrestore(&instance->hba_lock, flags); - printk(KERN_ERR "megaraid_sas: timed out while waiting" - "for HBA to recover.\n"); + dev_err(&instance->pdev->dev, "timed out while waiting" + "for HBA to recover\n"); return -ENODEV; } spin_unlock_irqrestore(&instance->hba_lock, flags); @@ -6502,7 +6498,7 @@ megasas_aen_polling(struct work_struct *work) if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) break; if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: %s waiting for " + dev_notice(&instance->pdev->dev, "%s waiting for " "controller reset to finish for scsi%d\n", __func__, instance->host->host_no); } @@ -6644,13 +6640,13 @@ megasas_aen_polling(struct work_struct *work) break; } } else { - printk(KERN_ERR "invalid evt_detail!\n"); + dev_err(&instance->pdev->dev, "invalid evt_detail!\n"); kfree(ev); return; } if (doscan) { - printk(KERN_INFO "megaraid_sas: scanning for scsi%d...\n", + dev_info(&instance->pdev->dev, "scanning for scsi%d...\n", instance->host->host_no); if (megasas_get_pd_list(instance) == 0) { for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { @@ -6722,7 +6718,7 @@ megasas_aen_polling(struct work_struct *work) mutex_unlock(&instance->aen_mutex); if (error) - printk(KERN_ERR "register aen failed error %x\n", error); + dev_err(&instance->pdev->dev, "register aen failed error %x\n", error); kfree(ev); } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 46a0f8f4f677..f0837cc3b163 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -221,7 +221,7 @@ static void megasas_teardown_frame_pool_fusion( struct megasas_cmd_fusion *cmd; if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) { - printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, " + dev_err(&instance->pdev->dev, "dma pool is null. SG Pool %p, " "sense pool : %p\n", fusion->sg_dma_pool, fusion->sense_dma_pool); return; @@ -332,8 +332,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) total_sz_chain_frame, 4, 0); if (!fusion->sg_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup request pool " - "fusion\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup request pool fusion\n"); return -ENOMEM; } fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion", @@ -341,8 +340,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) SCSI_SENSE_BUFFERSIZE, 64, 0); if (!fusion->sense_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup sense pool " - "fusion\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup sense pool fusion\n"); pci_pool_destroy(fusion->sg_dma_pool); fusion->sg_dma_pool = NULL; return -ENOMEM; @@ -366,7 +364,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) * whatever has been allocated */ if (!cmd->sg_frame || !cmd->sense) { - printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "pci_pool_alloc failed\n"); megasas_teardown_frame_pool_fusion(instance); return -ENOMEM; } @@ -412,7 +410,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) &fusion->req_frames_desc_phys, GFP_KERNEL); if (!fusion->req_frames_desc) { - printk(KERN_ERR "megasas; Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "request_frames\n"); goto fail_req_desc; } @@ -423,7 +421,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) fusion->reply_alloc_sz * count, 16, 0); if (!fusion->reply_frames_desc_pool) { - printk(KERN_ERR "megasas; Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "reply_frame pool\n"); goto fail_reply_desc; } @@ -432,7 +430,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL, &fusion->reply_frames_desc_phys); if (!fusion->reply_frames_desc) { - printk(KERN_ERR "megasas; Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "reply_frame pool\n"); pci_pool_destroy(fusion->reply_frames_desc_pool); goto fail_reply_desc; @@ -449,7 +447,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) fusion->io_frames_alloc_sz, 16, 0); if (!fusion->io_request_frames_pool) { - printk(KERN_ERR "megasas: Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "io_request_frame pool\n"); goto fail_io_frames; } @@ -458,7 +456,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL, &fusion->io_request_frames_phys); if (!fusion->io_request_frames) { - printk(KERN_ERR "megasas: Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "io_request_frames frames\n"); pci_pool_destroy(fusion->io_request_frames_pool); goto fail_io_frames; @@ -473,7 +471,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) * max_cmd, GFP_KERNEL); if (!fusion->cmd_list) { - printk(KERN_DEBUG "megasas: out of memory. Could not alloc " + dev_printk(KERN_DEBUG, &instance->pdev->dev, "out of memory. Could not alloc " "memory for cmd_list_fusion\n"); goto fail_cmd_list; } @@ -483,7 +481,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion), GFP_KERNEL); if (!fusion->cmd_list[i]) { - printk(KERN_ERR "Could not alloc cmd list fusion\n"); + dev_err(&instance->pdev->dev, "Could not alloc cmd list fusion\n"); for (j = 0; j < i; j++) kfree(fusion->cmd_list[j]); @@ -527,7 +525,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) * Create a frame pool and assign one frame to each cmd */ if (megasas_create_frame_pool_fusion(instance)) { - printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Error creating frame DMA pool\n"); megasas_free_cmds_fusion(instance); goto fail_req_desc; } @@ -613,7 +611,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_ERR "Could not allocate cmd for INIT Frame\n"); + dev_err(&instance->pdev->dev, "Could not allocate cmd for INIT Frame\n"); ret = 1; goto fail_get_cmd; } @@ -624,7 +622,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) &ioc_init_handle, GFP_KERNEL); if (!IOCInitMessage) { - printk(KERN_ERR "Could not allocate memory for " + dev_err(&instance->pdev->dev, "Could not allocate memory for " "IOCInitMessage\n"); ret = 1; goto fail_fw_init; @@ -714,7 +712,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ret = 1; goto fail_fw_init; } - printk(KERN_ERR "megasas:IOC Init cmd success\n"); + dev_err(&instance->pdev->dev, "Init cmd success\n"); ret = 0; @@ -757,7 +755,7 @@ megasas_get_ld_map_info(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for map info\n"); return -ENOMEM; } @@ -776,7 +774,7 @@ megasas_get_ld_map_info(struct megasas_instance *instance) ci_h = fusion->ld_map_phys[(instance->map_id & 1)]; if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for ld_map_info\n"); megasas_return_cmd(instance, cmd); return -ENOMEM; } @@ -851,8 +849,7 @@ megasas_sync_map_info(struct megasas_instance *instance) cmd = megasas_get_cmd(instance); if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get cmd for sync" - "info.\n"); + dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for sync info\n"); return -ENOMEM; } @@ -1097,7 +1094,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) &fusion->ld_map_phys[i], GFP_KERNEL); if (!fusion->ld_map[i]) { - printk(KERN_ERR "megasas: Could not allocate memory " + dev_err(&instance->pdev->dev, "Could not allocate memory " "for map info\n"); goto fail_map_info; } @@ -1162,7 +1159,7 @@ map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status) cmd->scmd->result = DID_IMM_RETRY << 16; break; default: - printk(KERN_DEBUG "megasas: FW status %#x\n", status); + dev_printk(KERN_DEBUG, &cmd->instance->pdev->dev, "FW status %#x\n", status); cmd->scmd->result = DID_ERROR << 16; break; } @@ -1851,7 +1848,7 @@ megasas_build_io_fusion(struct megasas_instance *instance, &io_request->SGL, cmd); if (sge_count > instance->max_num_sge) { - printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds " + dev_err(&instance->pdev->dev, "Error. sge_count (0x%x) exceeds " "max (0x%x) allowed\n", sge_count, instance->max_num_sge); return 1; @@ -1885,7 +1882,7 @@ megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) struct fusion_context *fusion; if (index >= instance->max_fw_cmds) { - printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for " + dev_err(&instance->pdev->dev, "Invalid SMID (0x%x)request for " "descriptor for scsi%d\n", index, instance->host->host_no); return NULL; @@ -1927,7 +1924,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, if (megasas_build_io_fusion(instance, scmd, cmd)) { megasas_return_cmd_fusion(instance, cmd); - printk(KERN_ERR "megasas: Error building command.\n"); + dev_err(&instance->pdev->dev, "Error building command\n"); cmd->request_desc = NULL; return 1; } @@ -1937,7 +1934,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, if (cmd->io_request->ChainOffset != 0 && cmd->io_request->ChainOffset != 0xF) - printk(KERN_ERR "megasas: The chain offset value is not " + dev_err(&instance->pdev->dev, "The chain offset value is not " "correct : %x\n", cmd->io_request->ChainOffset); /* @@ -2025,7 +2022,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { if (megasas_dbg_lvl == 5) - printk(KERN_ERR "\nmegasas: FAST Path " + dev_err(&instance->pdev->dev, "\nFAST Path " "IO Success\n"); } /* Fall thru and complete IO */ @@ -2186,7 +2183,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) else if (fw_state == MFI_STATE_FAULT) schedule_work(&instance->work_init); } else if (fw_state == MFI_STATE_FAULT) { - printk(KERN_WARNING "megaraid_sas: Iop2SysDoorbellInt" + dev_warn(&instance->pdev->dev, "Iop2SysDoorbellInt" "for scsi%d\n", instance->host->host_no); schedule_work(&instance->work_init); } @@ -2269,7 +2266,7 @@ build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) u16 index; if (build_mpt_mfi_pass_thru(instance, cmd)) { - printk(KERN_ERR "Couldn't build MFI pass thru cmd\n"); + dev_err(&instance->pdev->dev, "Couldn't build MFI pass thru cmd\n"); return NULL; } @@ -2303,7 +2300,7 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance, req_desc = build_mpt_cmd(instance, cmd); if (!req_desc) { - printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n"); + dev_err(&instance->pdev->dev, "Couldn't issue MFI pass thru cmd\n"); return; } megasas_fire_cmd_fusion(instance, req_desc); @@ -2413,7 +2410,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, fw_state = instance->instancet->read_fw_status_reg( instance->reg_set) & MFI_STATE_MASK; if (fw_state == MFI_STATE_FAULT) { - printk(KERN_WARNING "megasas: Found FW in FAULT state," + dev_warn(&instance->pdev->dev, "Found FW in FAULT state," " will reset adapter scsi%d.\n", instance->host->host_no); retval = 1; @@ -2436,7 +2433,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, hb_seconds_missed++; if (hb_seconds_missed == (MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) { - printk(KERN_WARNING "megasas: SR-IOV:" + dev_warn(&instance->pdev->dev, "SR-IOV:" " Heartbeat never completed " " while polling during I/O " " timeout handling for " @@ -2454,7 +2451,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, goto out; if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + dev_notice(&instance->pdev->dev, "[%2d]waiting for %d " "commands to complete for scsi%d\n", i, outstanding, instance->host->host_no); megasas_complete_cmd_dpc_fusion( @@ -2464,7 +2461,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, } if (atomic_read(&instance->fw_outstanding)) { - printk("megaraid_sas: pending commands remain after waiting, " + dev_err(&instance->pdev->dev, "pending commands remain after waiting, " "will reset adapter scsi%d.\n", instance->host->host_no); retval = 1; @@ -2564,7 +2561,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) mutex_lock(&instance->reset_mutex); if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - printk(KERN_WARNING "megaraid_sas: Hardware critical error, " + dev_warn(&instance->pdev->dev, "Hardware critical error, " "returning FAILED for scsi%d.\n", instance->host->host_no); mutex_unlock(&instance->reset_mutex); @@ -2618,7 +2615,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) if (megasas_wait_for_outstanding_fusion(instance, iotimeout, &convert)) { instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; - printk(KERN_WARNING "megaraid_sas: resetting fusion " + dev_warn(&instance->pdev->dev, "resetting fusion " "adapter scsi%d.\n", instance->host->host_no); if (convert) iotimeout = 0; @@ -2645,7 +2642,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) if (instance->disableOnlineCtrlReset || (abs_state == MFI_STATE_FAULT && !reset_adapter)) { /* Reset not supported, kill adapter */ - printk(KERN_WARNING "megaraid_sas: Reset not supported" + dev_warn(&instance->pdev->dev, "Reset not supported" ", killing adapter scsi%d.\n", instance->host->host_no); megaraid_sas_kill_hba(instance); @@ -2663,7 +2660,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) instance->hb_host_mem->HB.driverCounter)) { instance->hb_host_mem->HB.driverCounter = instance->hb_host_mem->HB.fwCounter; - printk(KERN_WARNING "megasas: SR-IOV:" + dev_warn(&instance->pdev->dev, "SR-IOV:" "Late FW heartbeat update for " "scsi%d.\n", instance->host->host_no); @@ -2679,8 +2676,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) abs_state = status_reg & MFI_STATE_MASK; if (abs_state == MFI_STATE_READY) { - printk(KERN_WARNING "megasas" - ": SR-IOV: FW was found" + dev_warn(&instance->pdev->dev, + "SR-IOV: FW was found" "to be in ready state " "for scsi%d.\n", instance->host->host_no); @@ -2689,7 +2686,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) msleep(20); } if (abs_state != MFI_STATE_READY) { - printk(KERN_WARNING "megasas: SR-IOV: " + dev_warn(&instance->pdev->dev, "SR-IOV: " "FW not in ready state after %d" " seconds for scsi%d, status_reg = " "0x%x.\n", @@ -2731,7 +2728,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) host_diag = readl(&instance->reg_set->fusion_host_diag); if (retry++ == 100) { - printk(KERN_WARNING "megaraid_sas: " + dev_warn(&instance->pdev->dev, "Host diag unlock failed! " "for scsi%d\n", instance->host->host_no); @@ -2754,7 +2751,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) host_diag = readl(&instance->reg_set->fusion_host_diag); if (retry++ == 1000) { - printk(KERN_WARNING "megaraid_sas: " + dev_warn(&instance->pdev->dev, "Diag reset adapter never " "cleared for scsi%d!\n", instance->host->host_no); @@ -2777,7 +2774,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) instance->reg_set) & MFI_STATE_MASK; } if (abs_state <= MFI_STATE_FW_INIT) { - printk(KERN_WARNING "megaraid_sas: firmware " + dev_warn(&instance->pdev->dev, "firmware " "state < MFI_STATE_FW_INIT, state = " "0x%x for scsi%d\n", abs_state, instance->host->host_no); @@ -2786,7 +2783,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) /* Wait for FW to become ready */ if (megasas_transition_to_ready(instance, 1)) { - printk(KERN_WARNING "megaraid_sas: Failed to " + dev_warn(&instance->pdev->dev, "Failed to " "transition controller to ready " "for scsi%d.\n", instance->host->host_no); @@ -2795,7 +2792,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) megasas_reset_reply_desc(instance); if (megasas_ioc_init_fusion(instance)) { - printk(KERN_WARNING "megaraid_sas: " + dev_warn(&instance->pdev->dev, "megasas_ioc_init_fusion() failed!" " for scsi%d\n", instance->host->host_no); @@ -2836,7 +2833,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) } /* Adapter reset completed successfully */ - printk(KERN_WARNING "megaraid_sas: Reset " + dev_warn(&instance->pdev->dev, "Reset " "successful for scsi%d.\n", instance->host->host_no); @@ -2852,7 +2849,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) goto out; } /* Reset failed, kill the adapter */ - printk(KERN_WARNING "megaraid_sas: Reset failed, killing " + dev_warn(&instance->pdev->dev, "Reset failed, killing " "adapter scsi%d.\n", instance->host->host_no); megaraid_sas_kill_hba(instance); instance->skip_heartbeat_timer_del = 1; From da0dc9fb4e6b0ad5a947c27a3c48985f6a2377eb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 7 Jul 2015 15:52:45 -0500 Subject: [PATCH 22/85] megaraid_sas: fix whitespace errors Fix whitespace and indentation errors. No code change. [jejb: checkpatch fixes] Signed-off-by: Bjorn Helgaas Reviewed-by: Hannes Reinecke Acked-by: Sumit Saxena Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 244 +++++++++++----------- 1 file changed, 118 insertions(+), 126 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index a9bd592fde37..eaa81e552fd2 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -273,6 +273,7 @@ static inline void megasas_enable_intr_xscale(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance->reg_set; writel(0, &(regs)->outbound_intr_mask); @@ -289,6 +290,7 @@ megasas_disable_intr_xscale(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0x1f; + regs = instance->reg_set; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -313,6 +315,7 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) { u32 status; u32 mfiStatus = 0; + /* * Check if it is our interrupt */ @@ -348,6 +351,7 @@ megasas_fire_cmd_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); writel((frame_phys_addr >> 3)|(frame_count), &(regs)->inbound_queue_port); @@ -364,6 +368,7 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, { u32 i; u32 pcidata; + writel(MFI_ADP_RESET, ®s->inbound_doorbell); for (i = 0; i < 3; i++) @@ -402,7 +407,6 @@ static int megasas_check_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { - if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && (le32_to_cpu(*instance->consumer) == MEGASAS_ADPRESET_INPROG_SIGN)) @@ -433,7 +437,7 @@ static struct megasas_instance_template megasas_instance_template_xscale = { /** * The following functions are defined for ppc (deviceid : 0x60) -* controllers +* controllers */ /** @@ -444,6 +448,7 @@ static inline void megasas_enable_intr_ppc(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance->reg_set; writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); @@ -462,6 +467,7 @@ megasas_disable_intr_ppc(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0xFFFFFFFF; + regs = instance->reg_set; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -522,6 +528,7 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); writel((frame_phys_addr | (frame_count<<1))|1, &(regs)->inbound_queue_port); @@ -566,6 +573,7 @@ static inline void megasas_enable_intr_skinny(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance->reg_set; writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); @@ -584,6 +592,7 @@ megasas_disable_intr_skinny(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0xFFFFFFFF; + regs = instance->reg_set; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -634,8 +643,8 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) writel(status, ®s->outbound_intr_status); /* - * dummy read to flush PCI - */ + * dummy read to flush PCI + */ readl(®s->outbound_intr_status); return mfiStatus; @@ -654,6 +663,7 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); writel(upper_32_bits(frame_phys_addr), &(regs)->inbound_high_queue_port); @@ -706,6 +716,7 @@ static inline void megasas_enable_intr_gen2(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; + regs = instance->reg_set; writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); @@ -725,6 +736,7 @@ megasas_disable_intr_gen2(struct megasas_instance *instance) { struct megasas_register_set __iomem *regs; u32 mask = 0xFFFFFFFF; + regs = instance->reg_set; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -750,6 +762,7 @@ megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) { u32 status; u32 mfiStatus = 0; + /* * Check if it is our interrupt */ @@ -786,6 +799,7 @@ megasas_fire_cmd_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); writel((frame_phys_addr | (frame_count<<1))|1, &(regs)->inbound_queue_port); @@ -800,10 +814,10 @@ static int megasas_adp_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem *reg_set) { - u32 retry = 0 ; - u32 HostDiag; - u32 __iomem *seq_offset = ®_set->seq_offset; - u32 __iomem *hostdiag_offset = ®_set->host_diag; + u32 retry = 0 ; + u32 HostDiag; + u32 __iomem *seq_offset = ®_set->seq_offset; + u32 __iomem *hostdiag_offset = ®_set->host_diag; if (instance->instancet == &megasas_instance_template_skinny) { seq_offset = ®_set->fusion_seq_offset; @@ -821,7 +835,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, HostDiag = (u32)readl(hostdiag_offset); - while ( !( HostDiag & DIAG_WRITE_ENABLE) ) { + while (!(HostDiag & DIAG_WRITE_ENABLE)) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); dev_notice(&instance->pdev->dev, "RESETGEN2: retry=%x, hostdiag=%x\n", @@ -839,7 +853,7 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, ssleep(10); HostDiag = (u32)readl(hostdiag_offset); - while ( ( HostDiag & DIAG_RESET_ADAPTER) ) { + while (HostDiag & DIAG_RESET_ADAPTER) { msleep(100); HostDiag = (u32)readl(hostdiag_offset); dev_notice(&instance->pdev->dev, "RESET_GEN2: retry=%x, hostdiag=%x\n", @@ -904,7 +918,6 @@ int megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) { int seconds; - struct megasas_header *frame_hdr = &cmd->frame->hdr; frame_hdr->cmd_status = MFI_CMD_STATUS_POLL_MODE; @@ -940,6 +953,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, int timeout) { int ret = 0; + cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; instance->instancet->issue_dcmd(instance, cmd); @@ -1120,7 +1134,7 @@ static u32 megasas_get_frame_count(struct megasas_instance *instance, int num_cnt; int sge_bytes; u32 sge_sz; - u32 frame_count=0; + u32 frame_count = 0; sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : sizeof(struct megasas_sge32); @@ -1151,14 +1165,14 @@ static u32 megasas_get_frame_count(struct megasas_instance *instance, num_cnt = sge_count - 3; } - if(num_cnt>0){ + if (num_cnt > 0) { sge_bytes = sge_sz * num_cnt; frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ; } /* Main frame */ - frame_count +=1; + frame_count += 1; if (frame_count > 7) frame_count = 8; @@ -1215,9 +1229,9 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); /* - * If the command is for the tape device, set the - * pthru timeout to the os layer timeout value. - */ + * If the command is for the tape device, set the + * pthru timeout to the os layer timeout value. + */ if (scp->device->type == TYPE_TAPE) { if ((scp->request->timeout / HZ) > 0xFFFF) pthru->timeout = cpu_to_le16(0xFFFF); @@ -1435,7 +1449,7 @@ inline int megasas_cmd_type(struct scsi_cmnd *cmd) /** * megasas_dump_pending_frames - Dumps the frame address of all pending cmds - * in FW + * in FW * @instance: Adapter soft state */ static inline void @@ -1459,7 +1473,7 @@ megasas_dump_pending_frames(struct megasas_instance *instance) dev_err(&instance->pdev->dev, "[%d]: Pending OS cmds in FW : \n",instance->host->host_no); for (i = 0; i < max_cmd; i++) { cmd = instance->cmd_list[i]; - if(!cmd->scmd) + if (!cmd->scmd) continue; dev_err(&instance->pdev->dev, "[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); if (megasas_cmd_type(cmd->scmd) == READ_WRITE_LDIO) { @@ -1471,8 +1485,7 @@ megasas_dump_pending_frames(struct megasas_instance *instance) instance->host->host_no, cmd->frame_count, ldio->cmd, ldio->target_id, le32_to_cpu(ldio->start_lba_lo), le32_to_cpu(ldio->start_lba_hi), le32_to_cpu(ldio->sense_buf_phys_addr_lo), sgcount); - } - else { + } else { pthru = (struct megasas_pthru_frame *) cmd->frame; mfi_sgl = &pthru->sgl; sgcount = pthru->sge_count; @@ -1482,16 +1495,16 @@ megasas_dump_pending_frames(struct megasas_instance *instance) pthru->lun, pthru->cdb_len, le32_to_cpu(pthru->data_xfer_len), le32_to_cpu(pthru->sense_buf_phys_addr_lo), sgcount); } - if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ - for (n = 0; n < sgcount; n++){ - if (IS_DMA64) - dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%llx\n", - le32_to_cpu(mfi_sgl->sge64[n].length), - le64_to_cpu(mfi_sgl->sge64[n].phys_addr)); - else - dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%x\n", - le32_to_cpu(mfi_sgl->sge32[n].length), - le32_to_cpu(mfi_sgl->sge32[n].phys_addr)); + if (megasas_dbg_lvl & MEGASAS_DBG_LVL) { + for (n = 0; n < sgcount; n++) { + if (IS_DMA64) + dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%llx\n", + le32_to_cpu(mfi_sgl->sge64[n].length), + le64_to_cpu(mfi_sgl->sge64[n].phys_addr)); + else + dev_err(&instance->pdev->dev, "sgl len : 0x%x, sgl addr : 0x%x\n", + le32_to_cpu(mfi_sgl->sge32[n].length), + le32_to_cpu(mfi_sgl->sge32[n].phys_addr)); } } } /*for max_cmd*/ @@ -1500,9 +1513,8 @@ megasas_dump_pending_frames(struct megasas_instance *instance) cmd = instance->cmd_list[i]; - if(cmd->sync_cmd == 1){ + if (cmd->sync_cmd == 1) dev_err(&instance->pdev->dev, "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); - } } dev_err(&instance->pdev->dev, "[%d]: Dumping Done\n\n",instance->host->host_no); } @@ -1650,8 +1662,8 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no) static int megasas_slave_configure(struct scsi_device *sdev) { /* - * The RAID firmware may require extended timeouts. - */ + * The RAID firmware may require extended timeouts. + */ blk_queue_rq_timeout(sdev->request_queue, MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); @@ -1660,8 +1672,9 @@ static int megasas_slave_configure(struct scsi_device *sdev) static int megasas_slave_alloc(struct scsi_device *sdev) { - u16 pd_index = 0; + u16 pd_index = 0; struct megasas_instance *instance ; + instance = megasas_lookup_instance(sdev->host->host_no); if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) { /* @@ -1727,8 +1740,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance) (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { - writel(MFI_STOP_ADP, - &instance->reg_set->doorbell); + writel(MFI_STOP_ADP, &instance->reg_set->doorbell); /* Flush */ readl(&instance->reg_set->doorbell); if (instance->mpio && instance->requestorId) @@ -1782,7 +1794,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) unsigned long flags; /* If we have already declared adapter dead, donot complete cmds */ - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) return; spin_lock_irqsave(&instance->completion_lock, flags); @@ -2285,14 +2297,14 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) if (adprecovery != MEGASAS_HBA_OPERATIONAL) { dev_notice(&instance->pdev->dev, "reset: Stopping HBA.\n"); spin_lock_irqsave(&instance->hba_lock, flags); - instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; spin_unlock_irqrestore(&instance->hba_lock, flags); return FAILED; } - reset_index = 0; + reset_index = 0; while (!list_empty(&clist_local)) { - reset_cmd = list_entry((&clist_local)->next, + reset_cmd = list_entry((&clist_local)->next, struct megasas_cmd, list); list_del_init(&reset_cmd->list); if (reset_cmd->scmd) { @@ -2324,7 +2336,6 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) } for (i = 0; i < resetwaittime; i++) { - int outstanding = atomic_read(&instance->fw_outstanding); if (!outstanding) @@ -2363,10 +2374,8 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) i++; } while (i <= 3); - if (atomic_read(&instance->fw_outstanding) && - !kill_adapter_flag) { + if (atomic_read(&instance->fw_outstanding) && !kill_adapter_flag) { if (instance->disableOnlineCtrlReset == 0) { - megasas_do_ocr(instance); /* wait for 5 secs to let FW finish the pending cmds */ @@ -2384,9 +2393,9 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) (kill_adapter_flag == 2)) { dev_notice(&instance->pdev->dev, "pending cmds after reset\n"); /* - * Send signal to FW to stop processing any pending cmds. - * The controller will be taken offline by the OS now. - */ + * Send signal to FW to stop processing any pending cmds. + * The controller will be taken offline by the OS now. + */ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == @@ -2399,7 +2408,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) } megasas_dump_pending_frames(instance); spin_lock_irqsave(&instance->hba_lock, flags); - instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; spin_unlock_irqrestore(&instance->hba_lock, flags); return FAILED; } @@ -2478,14 +2487,10 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) */ static int megasas_reset_device(struct scsi_cmnd *scmd) { - int ret; - /* * First wait for all commands to complete */ - ret = megasas_generic_reset(scmd); - - return ret; + return megasas_generic_reset(scmd); } /** @@ -2495,6 +2500,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) { int ret; struct megasas_instance *instance; + instance = (struct megasas_instance *)scmd->device->host->hostdata; /* @@ -2513,7 +2519,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) /** * megasas_bios_param - Returns disk geometry for a disk - * @sdev: device handle + * @sdev: device handle * @bdev: block device * @capacity: drive capacity * @geom: geometry parameters @@ -2526,6 +2532,7 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, int sectors; sector_t cylinders; unsigned long tmp; + /* Default heads (64) & sectors (32) */ heads = 64; sectors = 32; @@ -2572,6 +2579,7 @@ static void megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) { unsigned long flags; + /* * Don't signal app if it is just an aborted previously registered aen */ @@ -2592,6 +2600,7 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) if ((instance->unload == 0) && ((instance->issuepend_done == 1))) { struct megasas_aen_event *ev; + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { dev_err(&instance->pdev->dev, "megasas_service_aen: out of memory\n"); @@ -2651,8 +2660,7 @@ megasas_fw_crash_buffer_show(struct device *cdev, buff_addr = (unsigned long) buf; - if (buff_offset > - (instance->fw_crash_buffer_size * dmachunk)) { + if (buff_offset > (instance->fw_crash_buffer_size * dmachunk)) { dev_err(&instance->pdev->dev, "Firmware crash dump offset is out of range\n"); spin_unlock_irqrestore(&instance->crashdump_lock, flags); @@ -2664,7 +2672,7 @@ megasas_fw_crash_buffer_show(struct device *cdev, src_addr = (unsigned long)instance->crash_buf[buff_offset / dmachunk] + (buff_offset % dmachunk); - memcpy(buf, (void *)src_addr, size); + memcpy(buf, (void *)src_addr, size); spin_unlock_irqrestore(&instance->crashdump_lock, flags); return size; @@ -2724,6 +2732,7 @@ megasas_fw_crash_state_show(struct device *cdev, struct Scsi_Host *shost = class_to_shost(cdev); struct megasas_instance *instance = (struct megasas_instance *) shost->hostdata; + return snprintf(buf, PAGE_SIZE, "%d\n", instance->fw_crash_state); } @@ -2808,8 +2817,6 @@ megasas_complete_abort(struct megasas_instance *instance, cmd->cmd_status_drv = 0; wake_up(&instance->abort_cmd_wait_q); } - - return; } /** @@ -2817,10 +2824,10 @@ megasas_complete_abort(struct megasas_instance *instance, * @instance: Adapter soft state * @cmd: Command to be completed * @alt_status: If non-zero, use this value as status to - * SCSI mid-layer instead of the value returned - * by the FW. This should be used if caller wants - * an alternate status (as in the case of aborted - * commands) + * SCSI mid-layer instead of the value returned + * by the FW. This should be used if caller wants + * an alternate status (as in the case of aborted + * commands) */ void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, @@ -3001,7 +3008,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, /** * megasas_issue_pending_cmds_again - issue all pending cmds - * in FW again because of the fw reset + * in FW again because of the fw reset * @instance: Adapter soft state */ static inline void @@ -3019,7 +3026,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) spin_unlock_irqrestore(&instance->hba_lock, flags); while (!list_empty(&clist_local)) { - cmd = list_entry((&clist_local)->next, + cmd = list_entry((&clist_local)->next, struct megasas_cmd, list); list_del_init(&cmd->list); @@ -3052,7 +3059,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) "issue it again.\n", cmd); cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr , + cmd->frame_phys_addr, 0, instance->reg_set); } else if (cmd->scmd) { dev_notice(&instance->pdev->dev, "%p scsi cmd [%02x]" @@ -3074,12 +3081,12 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) dev_notice(&instance->pdev->dev, "aen_cmd in def process\n"); megasas_return_cmd(instance, instance->aen_cmd); - instance->aen_cmd = NULL; + instance->aen_cmd = NULL; } /* - * Initiate AEN (Asynchronous Event Notification) - */ + * Initiate AEN (Asynchronous Event Notification) + */ seq_num = instance->last_seq_num; class_locale.members.reserved = 0; class_locale.members.locale = MR_EVT_LOCALE_ALL; @@ -3106,7 +3113,7 @@ megasas_internal_reset_defer_cmds(struct megasas_instance *instance) u32 defer_index; unsigned long flags; - defer_index = 0; + defer_index = 0; spin_lock_irqsave(&instance->mfi_pool_lock, flags); for (i = 0; i < max_cmd; i++) { cmd = instance->cmd_list[i]; @@ -3155,7 +3162,7 @@ process_fw_state_change_wq(struct work_struct *work) atomic_set(&instance->fw_reset_no_pci_access, 1); instance->instancet->adp_reset(instance, instance->reg_set); - atomic_set(&instance->fw_reset_no_pci_access, 0 ); + atomic_set(&instance->fw_reset_no_pci_access, 0); dev_notice(&instance->pdev->dev, "FW restarted successfully," "initiating next stage...\n"); @@ -3163,7 +3170,7 @@ process_fw_state_change_wq(struct work_struct *work) dev_notice(&instance->pdev->dev, "HBA recovery state machine," "state 2 starting...\n"); - /*waitting for about 20 second before start the second init*/ + /* waiting for about 20 second before start the second init */ for (wait = 0; wait < 30; wait++) { msleep(1000); } @@ -3196,15 +3203,14 @@ process_fw_state_change_wq(struct work_struct *work) megasas_issue_pending_cmds_again(instance); instance->issuepend_done = 1; } - return ; } /** * megasas_deplete_reply_queue - Processes all completed commands * @instance: Adapter soft state * @alt_status: Alternate status to be returned to - * SCSI mid-layer instead of the status - * returned by the FW + * SCSI mid-layer instead of the status + * returned by the FW * Note: this must be called with hba lock held */ static int @@ -3284,13 +3290,13 @@ static irqreturn_t megasas_isr(int irq, void *devp) struct megasas_irq_context *irq_context = devp; struct megasas_instance *instance = irq_context->instance; unsigned long flags; - irqreturn_t rc; + irqreturn_t rc; if (atomic_read(&instance->fw_reset_no_pci_access)) return IRQ_HANDLED; spin_lock_irqsave(&instance->hba_lock, flags); - rc = megasas_deplete_reply_queue(instance, DID_OK); + rc = megasas_deplete_reply_queue(instance, DID_OK); spin_unlock_irqrestore(&instance->hba_lock, flags); return rc; @@ -3566,9 +3572,8 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : sizeof(struct megasas_sge32); - if (instance->flag_ieee) { + if (instance->flag_ieee) sge_sz = sizeof(struct megasas_sge_skinny); - } /* * For MFI controllers. @@ -3652,6 +3657,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) void megasas_free_cmds(struct megasas_instance *instance) { int i; + /* First free the MFI frame pool */ megasas_teardown_frame_pool(instance); @@ -3807,12 +3813,12 @@ megasas_get_pd_list(struct megasas_instance *instance) ret = megasas_issue_polled(instance, cmd); /* - * the following function will get the instance PD LIST. - */ + * the following function will get the instance PD LIST. + */ pd_addr = ci->addr; - if ( ret == 0 && + if (ret == 0 && (le32_to_cpu(ci->count) < (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { @@ -4048,11 +4054,11 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) instance->supportmax256vd ? "Extended VD(240 VD)firmware" : "Legacy(64 VD) firmware"); - old_map_sz = sizeof(struct MR_FW_RAID_MAP) + + old_map_sz = sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) * (instance->fw_supported_vd_count - 1)); - new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT); - fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP) + + new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT); + fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) * (instance->drv_supported_vd_count - 1)); @@ -4063,7 +4069,6 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) fusion->current_map_sz = new_map_sz; else fusion->current_map_sz = old_map_sz; - } /** @@ -4210,9 +4215,7 @@ static int megasas_issue_init_mfi(struct megasas_instance *instance) { __le32 context; - struct megasas_cmd *cmd; - struct megasas_init_frame *init_frame; struct megasas_init_queue_info *initq_info; dma_addr_t init_frame_h; @@ -4651,10 +4654,9 @@ static int megasas_init_fw(struct megasas_instance *instance) dev_err(&instance->pdev->dev, "INIT adapter done\n"); /** for passthrough - * the following function will get the PD LIST. - */ - - memset(instance->pd_list, 0 , + * the following function will get the PD LIST. + */ + memset(instance->pd_list, 0, (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); if (megasas_get_pd_list(instance) < 0) { dev_err(&instance->pdev->dev, "failed to get PD list\n"); @@ -4682,7 +4684,7 @@ static int megasas_init_fw(struct megasas_instance *instance) le16_to_cpu(ctrl_info->max_strips_per_io); max_sectors_2 = le32_to_cpu(ctrl_info->max_request_size); - tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); + tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2); instance->disableOnlineCtrlReset = ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; @@ -5047,7 +5049,7 @@ static int megasas_start_aen(struct megasas_instance *instance) static int megasas_io_attach(struct megasas_instance *instance) { struct Scsi_Host *host = instance->host; - u32 error; + u32 error; /* * Export parameters required by SCSI mid-layer @@ -5122,7 +5124,7 @@ static int megasas_set_dma_mask(struct pci_dev *pdev) { /* - * All our contollers are capable of performing 64-bit DMA + * All our controllers are capable of performing 64-bit DMA */ if (IS_DMA64) { if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { @@ -5208,7 +5210,7 @@ static int megasas_probe_one(struct pci_dev *pdev, instance = (struct megasas_instance *)host->hostdata; memset(instance, 0, sizeof(*instance)); - atomic_set( &instance->fw_reset_no_pci_access, 0 ); + atomic_set(&instance->fw_reset_no_pci_access, 0); instance->pdev = pdev; switch (instance->pdev->device) { @@ -5405,8 +5407,8 @@ static int megasas_probe_one(struct pci_dev *pdev, return 0; - fail_start_aen: - fail_io_attach: +fail_start_aen: +fail_io_attach: megasas_mgmt_info.count--; megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; megasas_mgmt_info.max_index--; @@ -5424,7 +5426,7 @@ static int megasas_probe_one(struct pci_dev *pdev, if (instance->msix_vectors) pci_disable_msix(instance->pdev); fail_init_mfi: - fail_alloc_dma_buf: +fail_alloc_dma_buf: if (instance->evt_detail) pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), instance->evt_detail, @@ -5438,8 +5440,8 @@ fail_init_mfi: instance->consumer_h); scsi_host_put(host); - fail_alloc_instance: - fail_set_dma_mask: +fail_alloc_instance: +fail_set_dma_mask: pci_disable_device(pdev); return -ENODEV; @@ -5481,8 +5483,6 @@ static void megasas_flush_cache(struct megasas_instance *instance) " from %s\n", __func__); megasas_return_cmd(instance, cmd); - - return; } /** @@ -5528,8 +5528,6 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, "from %s\n", __func__); megasas_return_cmd(instance, cmd); - - return; } #ifdef CONFIG_PM @@ -5835,8 +5833,6 @@ static void megasas_detach_one(struct pci_dev *pdev) scsi_host_put(host); pci_disable_device(pdev); - - return; } /** @@ -5905,11 +5901,11 @@ static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) { unsigned int mask; unsigned long flags; + poll_wait(file, &megasas_poll_wait, wait); spin_lock_irqsave(&poll_aen_lock, flags); if (megasas_poll_wait_aen) - mask = (POLLIN | POLLRDNORM); - + mask = (POLLIN | POLLRDNORM); else mask = 0; megasas_poll_wait_aen = 0; @@ -5923,8 +5919,7 @@ static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) * @cmd: MFI command frame */ -static int megasas_set_crash_dump_params_ioctl( - struct megasas_cmd *cmd) +static int megasas_set_crash_dump_params_ioctl(struct megasas_cmd *cmd) { struct megasas_instance *local_instance; int i, error = 0; @@ -6120,7 +6115,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, error = -EFAULT; } - out: +out: if (sense) { dma_free_coherent(&instance->pdev->dev, ioc->sense_len, sense, sense_handle); @@ -6220,10 +6215,10 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) spin_unlock_irqrestore(&instance->hba_lock, flags); error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); - out_up: +out_up: up(&instance->ioctl_sem); - out_kfree_ioc: +out_kfree_ioc: kfree(ioc); return error; } @@ -6458,7 +6453,8 @@ static ssize_t megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count) { int retval = count; - if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){ + + if (sscanf(buf, "%u", &megasas_dbg_lvl) < 1) { printk(KERN_ERR "megasas: could not set dbg_lvl\n"); retval = -EINVAL; } @@ -6520,14 +6516,12 @@ megasas_aen_polling(struct work_struct *work) pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - sdev1 = - scsi_device_lookup(host, i, j, 0); + sdev1 = scsi_device_lookup(host, i, j, 0); if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) { - if (!sdev1) { + if (!sdev1) scsi_add_device(host, i, j, 0); - } if (sdev1) scsi_device_put(sdev1); @@ -6548,14 +6542,12 @@ megasas_aen_polling(struct work_struct *work) pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - sdev1 = - scsi_device_lookup(host, i, j, 0); + sdev1 = scsi_device_lookup(host, i, j, 0); if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) { - if (sdev1) { + if (sdev1) scsi_device_put(sdev1); - } } else { if (sdev1) { scsi_remove_device(sdev1); @@ -6701,7 +6693,7 @@ megasas_aen_polling(struct work_struct *work) } } - if ( instance->aen_cmd != NULL ) { + if (instance->aen_cmd != NULL) { kfree(ev); return ; } From 2d3a5d215e24d9bfb822ae82c6c2c5d333be076d Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 8 Jul 2015 17:24:01 +0200 Subject: [PATCH 23/85] st: Destroy st_index_idr on module exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Destroy st_index_idr on module exit, reclaiming the allocated memory. This was detected by the following semantic patch (written by Luis Rodriguez ) @ defines_module_init @ declarer name module_init, module_exit; declarer name DEFINE_IDR; identifier init; @@ module_init(init); @ defines_module_exit @ identifier exit; @@ module_exit(exit); @ declares_idr depends on defines_module_init && defines_module_exit @ identifier idr; @@ DEFINE_IDR(idr); @ on_exit_calls_destroy depends on declares_idr && defines_module_exit @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... idr_destroy(&idr); ... } @ missing_module_idr_destroy depends on declares_idr && defines_module_exit && !on_exit_calls_destroy @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... +idr_destroy(&idr); } Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Kai Mäkisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 9cf3272daa69..b37b9b00c4b4 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4419,6 +4419,7 @@ static void __exit exit_st(void) unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); class_unregister(&st_sysfs_class); + idr_destroy(&st_index_idr); printk(KERN_INFO "st: Unloaded.\n"); } From c3ff356d08275960b4a36471a81d5b2685a4074e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:22:38 -0700 Subject: [PATCH 24/85] qla2xxx: Report both rsp_info and rsp_info_len Let the debug statement in qlafx00_tm_iocb_entry() report both rsp_info and rsp_info_len instead of reporting rsp_info_len twice. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 6d190b4b82a0..878fd3d961f8 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -2528,12 +2528,12 @@ check_scsi_status: ql_dbg(ql_dbg_io, fcport->vha, 0x3058, "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x " - "rsp_info=0x%x resid=0x%x fw_resid=0x%x sense_len=0x%x, " + "rsp_info=%p resid=0x%x fw_resid=0x%x sense_len=0x%x, " "par_sense_len=0x%x, rsp_info_len=0x%x\n", comp_status, scsi_status, res, vha->host_no, cp->device->id, cp->device->lun, fcport->tgt_id, lscsi_status, cp->cmnd, scsi_bufflen(cp), - rsp_info_len, resid_len, fw_resid_len, sense_len, + rsp_info, resid_len, fw_resid_len, sense_len, par_sense_len, rsp_info_len); if (rsp->status_srb == NULL) From 2374dd238c287fb7a370b53aad2dbc4c8f0c241c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:23:02 -0700 Subject: [PATCH 25/85] qla2xxx: Declare local functions static Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 4 ++-- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla2xxx/qla_nx2.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 2e2bb6f45ce6..e1c2a57a882f 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -405,7 +405,7 @@ done: return rval; } -inline uint16_t +static inline uint16_t qla24xx_calc_ct_iocbs(uint16_t dsds) { uint16_t iocbs; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 36fbd4c7af8f..d58ffb79c064 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -680,7 +680,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, * * Returns the number of dsd list needed to store @dsds. */ -inline uint16_t +static inline uint16_t qla24xx_calc_dsd_lists(uint16_t dsds) { uint16_t dsd_lists = 0; @@ -700,7 +700,7 @@ qla24xx_calc_dsd_lists(uint16_t dsds) * @cmd_pkt: Command type 3 IOCB * @tot_dsds: Total number of segments to transfer */ -inline void +static inline void qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, uint16_t tot_dsds) { diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 1620b0ec977b..47f8419adf41 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2298,7 +2298,7 @@ void qla82xx_init_flags(struct qla_hw_data *ha) ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; } -inline void +static inline void qla82xx_set_idc_version(scsi_qla_host_t *vha) { int idc_ver; diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 000c57e4d033..e06c851147d0 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -561,7 +561,7 @@ qla8044_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, return buf; } -inline int +static inline int qla8044_need_reset(struct scsi_qla_host *vha) { uint32_t drv_state, drv_active; @@ -1605,7 +1605,7 @@ qla8044_set_idc_dontreset(struct scsi_qla_host *vha) qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, idc_ctrl); } -inline void +static inline void qla8044_set_rst_ready(struct scsi_qla_host *vha) { uint32_t drv_state; From 52c82823cc686d4faf9e9bc4feec4bf48c36fded Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:23:26 -0700 Subject: [PATCH 26/85] qla2xxx: Remove set-but-not-used variables Detected these variables by building with W=1. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 -- drivers/scsi/qla2xxx/qla_bsg.c | 5 ----- drivers/scsi/qla2xxx/qla_dbg.c | 24 ++++++------------------ drivers/scsi/qla2xxx/qla_init.c | 10 ++++------ drivers/scsi/qla2xxx/qla_iocb.c | 24 +++--------------------- drivers/scsi/qla2xxx/qla_isr.c | 3 +-- drivers/scsi/qla2xxx/qla_mbx.c | 4 ---- drivers/scsi/qla2xxx/qla_mid.c | 3 +-- drivers/scsi/qla2xxx/qla_mr.c | 10 +++------- drivers/scsi/qla2xxx/qla_nx.c | 9 +++------ drivers/scsi/qla2xxx/qla_nx2.c | 12 ++++-------- drivers/scsi/qla2xxx/qla_os.c | 6 ++---- drivers/scsi/qla2xxx/qla_target.c | 19 ++++--------------- drivers/scsi/qla2xxx/qla_tmpl.c | 3 +-- 14 files changed, 32 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 82b92c414a9c..741d6e0f4060 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -884,7 +884,6 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; int rval; - uint16_t actual_size; if (!capable(CAP_SYS_ADMIN) || off != 0 || count > DCBX_TLV_DATA_SIZE) return 0; @@ -901,7 +900,6 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj, } do_read: - actual_size = 0; memset(ha->dcbx_tlv, 0, DCBX_TLV_DATA_SIZE); rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma, diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index e1c2a57a882f..c26acde797f0 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1733,7 +1733,6 @@ qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) struct Scsi_Host *host = bsg_job->shost; scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; - uint16_t thread_id; uint32_t rval = EXT_STATUS_OK; uint16_t req_sg_cnt = 0; uint16_t rsp_sg_cnt = 0; @@ -1790,8 +1789,6 @@ qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) goto done; } - thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; - mutex_lock(&ha->selflogin_lock); if (vha->self_login_loop_id == 0) { /* Initialize all required fields of fcport */ @@ -2174,7 +2171,6 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) { int ret = -EINVAL; struct fc_rport *rport; - fc_port_t *fcport = NULL; struct Scsi_Host *host; scsi_qla_host_t *vha; @@ -2183,7 +2179,6 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { rport = bsg_job->rport; - fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 0e6ee3ca30e6..121ed5bdb4fa 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -117,7 +117,7 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, { int rval; uint32_t cnt, stat, timer, dwords, idx; - uint16_t mb0, mb1; + uint16_t mb0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t dump_dma = ha->gid_list_dma; uint32_t *dump = (uint32_t *)ha->gid_list; @@ -161,7 +161,7 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, &ha->mbx_cmd_flags); mb0 = RD_REG_WORD(®->mailbox0); - mb1 = RD_REG_WORD(®->mailbox1); + RD_REG_WORD(®->mailbox1); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); @@ -1039,7 +1039,6 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) { int rval; uint32_t cnt; - uint32_t risc_address; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1047,7 +1046,6 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) uint16_t __iomem *mbx_reg; unsigned long flags; struct qla24xx_fw_dump *fw; - uint32_t ext_mem_cnt; void *nxt; void *nxt_chain; uint32_t *last_chain = NULL; @@ -1056,7 +1054,6 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (IS_P3P_TYPE(ha)) return; - risc_address = ext_mem_cnt = 0; flags = 0; ha->fw_dump_cap_flags = 0; @@ -1294,7 +1291,6 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) { int rval; uint32_t cnt; - uint32_t risc_address; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1302,12 +1298,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) uint16_t __iomem *mbx_reg; unsigned long flags; struct qla25xx_fw_dump *fw; - uint32_t ext_mem_cnt; void *nxt, *nxt_chain; uint32_t *last_chain = NULL; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); - risc_address = ext_mem_cnt = 0; flags = 0; ha->fw_dump_cap_flags = 0; @@ -1613,7 +1607,6 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) { int rval; uint32_t cnt; - uint32_t risc_address; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1621,12 +1614,10 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) uint16_t __iomem *mbx_reg; unsigned long flags; struct qla81xx_fw_dump *fw; - uint32_t ext_mem_cnt; void *nxt, *nxt_chain; uint32_t *last_chain = NULL; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); - risc_address = ext_mem_cnt = 0; flags = 0; ha->fw_dump_cap_flags = 0; @@ -1933,8 +1924,7 @@ void qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) { int rval; - uint32_t cnt, reg_data; - uint32_t risc_address; + uint32_t cnt; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1942,12 +1932,10 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) uint16_t __iomem *mbx_reg; unsigned long flags; struct qla83xx_fw_dump *fw; - uint32_t ext_mem_cnt; void *nxt, *nxt_chain; uint32_t *last_chain = NULL; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); - risc_address = ext_mem_cnt = 0; flags = 0; ha->fw_dump_cap_flags = 0; @@ -1979,16 +1967,16 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) WRT_REG_DWORD(®->iobase_addr, 0x6000); dmp_reg = ®->iobase_window; - reg_data = RD_REG_DWORD(dmp_reg); + RD_REG_DWORD(dmp_reg); WRT_REG_DWORD(dmp_reg, 0); dmp_reg = ®->unused_4_1[0]; - reg_data = RD_REG_DWORD(dmp_reg); + RD_REG_DWORD(dmp_reg); WRT_REG_DWORD(dmp_reg, 0); WRT_REG_DWORD(®->iobase_addr, 0x6010); dmp_reg = ®->unused_4_1[2]; - reg_data = RD_REG_DWORD(dmp_reg); + RD_REG_DWORD(dmp_reg); WRT_REG_DWORD(dmp_reg, 0); /* select PCR and disable ecc checking and correction */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 664013115c9d..f4a64a4fc40a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1127,7 +1127,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) unsigned long flags = 0; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - uint32_t cnt, d2; + uint32_t cnt; uint16_t wd; static int abts_cnt; /* ISP abort retry counts */ int rval = QLA_SUCCESS; @@ -1159,7 +1159,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) udelay(100); /* Wait for firmware to complete NVRAM accesses. */ - d2 = (uint32_t) RD_REG_WORD(®->mailbox0); + RD_REG_WORD(®->mailbox0); for (cnt = 10000; RD_REG_WORD(®->mailbox0) != 0 && rval == QLA_SUCCESS; cnt--) { barrier(); @@ -1178,7 +1178,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) RD_REG_DWORD(®->mailbox0)); /* Wait for soft-reset to complete. */ - d2 = RD_REG_DWORD(®->ctrl_status); + RD_REG_DWORD(®->ctrl_status); for (cnt = 0; cnt < 6000000; cnt++) { barrier(); if ((RD_REG_DWORD(®->ctrl_status) & @@ -1221,7 +1221,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); RD_REG_DWORD(®->hccr); - d2 = (uint32_t) RD_REG_WORD(®->mailbox0); + RD_REG_WORD(®->mailbox0); for (cnt = 6000000; RD_REG_WORD(®->mailbox0) != 0 && rval == QLA_SUCCESS; cnt--) { barrier(); @@ -3856,12 +3856,10 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t *next_loopid) { int rval; - int retry; uint8_t opts; struct qla_hw_data *ha = vha->hw; rval = QLA_SUCCESS; - retry = 0; if (IS_ALOGIO_CAPABLE(ha)) { if (fcport->flags & FCF_ASYNC_SENT) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d58ffb79c064..e95162e1fcb7 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -310,7 +310,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, int qla2x00_start_scsi(srb_t *sp) { - int ret, nseg; + int nseg; unsigned long flags; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; @@ -327,7 +327,6 @@ qla2x00_start_scsi(srb_t *sp) struct rsp_que *rsp; /* Setup device pointers. */ - ret = 0; vha = sp->fcport->vha; ha = vha->hw; reg = &ha->iobase->isp; @@ -710,7 +709,6 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, struct scsi_cmnd *cmd; struct scatterlist *sg; int i; - struct req_que *req; cmd = GET_CMD_SP(sp); @@ -725,7 +723,6 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, } vha = sp->fcport->vha; - req = vha->req; /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { @@ -933,11 +930,9 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, dma_addr_t sle_dma; uint32_t sle_dma_len, tot_prot_dma_len = 0; struct scsi_cmnd *cmd; - struct scsi_qla_host *vha; memset(&sgx, 0, sizeof(struct qla2_sgx)); if (sp) { - vha = sp->fcport->vha; cmd = GET_CMD_SP(sp); prot_int = cmd->device->sector_size; @@ -947,7 +942,6 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, sg_prot = scsi_prot_sglist(cmd); } else if (tc) { - vha = tc->vha; prot_int = tc->blk_sz; sgx.tot_bytes = tc->bufflen; sgx.cur_sg = tc->sg; @@ -1047,15 +1041,12 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, int i; uint16_t used_dsds = tot_dsds; struct scsi_cmnd *cmd; - struct scsi_qla_host *vha; if (sp) { cmd = GET_CMD_SP(sp); sgl = scsi_sglist(cmd); - vha = sp->fcport->vha; } else if (tc) { sgl = tc->sg; - vha = tc->vha; } else { BUG(); return 1; @@ -1231,7 +1222,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, uint32_t *cur_dsd, *fcp_dl; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; - int sgc; uint32_t total_bytes = 0; uint32_t data_bytes; uint32_t dif_bytes; @@ -1247,7 +1237,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd = GET_CMD_SP(sp); - sgc = 0; /* Update entry type to indicate Command Type CRC_2 IOCB */ *((uint32_t *)(&cmd_pkt->entry_type)) = __constant_cpu_to_le32(COMMAND_TYPE_CRC_2); @@ -1442,7 +1431,7 @@ crc_queuing_error: int qla24xx_start_scsi(srb_t *sp) { - int ret, nseg; + int nseg; unsigned long flags; uint32_t *clr_ptr; uint32_t index; @@ -1458,8 +1447,6 @@ qla24xx_start_scsi(srb_t *sp) struct qla_hw_data *ha = vha->hw; /* Setup device pointers. */ - ret = 0; - qla25xx_set_que(sp, &rsp); req = vha->req; @@ -2088,7 +2075,6 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) struct qla_hw_data *ha = vha->hw; struct fc_bsg_job *bsg_job = sp->u.bsg_job; int loop_iterartion = 0; - int cont_iocb_prsnt = 0; int entry_count = 1; memset(ct_iocb, 0, sizeof(ms_iocb_entry_t)); @@ -2139,7 +2125,6 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) vha->hw->req_q_map[0]); cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; avail_dsds = 5; - cont_iocb_prsnt = 1; entry_count++; } @@ -2167,7 +2152,6 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) struct qla_hw_data *ha = vha->hw; struct fc_bsg_job *bsg_job = sp->u.bsg_job; int loop_iterartion = 0; - int cont_iocb_prsnt = 0; int entry_count = 1; ct_iocb->entry_type = CT_IOCB_TYPE; @@ -2214,7 +2198,6 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) ha->req_q_map[0]); cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; avail_dsds = 5; - cont_iocb_prsnt = 1; entry_count++; } @@ -2237,7 +2220,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) int qla82xx_start_scsi(srb_t *sp) { - int ret, nseg; + int nseg; unsigned long flags; struct scsi_cmnd *cmd; uint32_t *clr_ptr; @@ -2257,7 +2240,6 @@ qla82xx_start_scsi(srb_t *sp) struct rsp_que *rsp = NULL; /* Setup device pointers. */ - ret = 0; reg = &ha->iobase->isp82; cmd = GET_CMD_SP(sp); req = vha->req; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index dcfa4655ce43..a526c389fa2f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -575,7 +575,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; - uint32_t rscn_entry, host_pid, tmp_pid; + uint32_t rscn_entry, host_pid; unsigned long flags; fc_port_t *fcport = NULL; @@ -998,7 +998,6 @@ skip_rio: list_for_each_entry(fcport, &vha->vp_fcports, list) { if (atomic_read(&fcport->state) != FCS_ONLINE) continue; - tmp_pid = fcport->d_id.b24; if (fcport->d_id.b24 == rscn_entry) { qla2x00_mark_device_lost(vha, fcport, 0, 0); break; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 02b1c1c5355b..65c2dc1e929a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1865,7 +1865,6 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, uint32_t iop[2]; struct qla_hw_data *ha = vha->hw; struct req_que *req; - struct rsp_que *rsp; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061, "Entered %s.\n", __func__); @@ -1874,7 +1873,6 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, req = ha->req_q_map[0]; else req = vha->req; - rsp = req->rsp; lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); if (lg == NULL) { @@ -2142,7 +2140,6 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, dma_addr_t lg_dma; struct qla_hw_data *ha = vha->hw; struct req_que *req; - struct rsp_que *rsp; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d, "Entered %s.\n", __func__); @@ -2159,7 +2156,6 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, req = ha->req_q_map[0]; else req = vha->req; - rsp = req->rsp; lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; lg->handle = MAKE_HANDLE(req->id, lg->handle); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index cc94192511cf..c5dd594f6c31 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -371,7 +371,6 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) void qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) { - int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; unsigned long flags = 0; @@ -392,7 +391,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) atomic_inc(&vp->vref_count); spin_unlock_irqrestore(&ha->vport_slock, flags); - ret = qla2x00_do_dpc_vp(vp); + qla2x00_do_dpc_vp(vp); spin_lock_irqsave(&ha->vport_slock, flags); atomic_dec(&vp->vref_count); diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 878fd3d961f8..1843ba91e2c8 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -1317,10 +1317,10 @@ int qlafx00_configure_devices(scsi_qla_host_t *vha) { int rval; - unsigned long flags, save_flags; + unsigned long flags; rval = QLA_SUCCESS; - save_flags = flags = vha->dpc_flags; + flags = vha->dpc_flags; ql_dbg(ql_dbg_disc, vha, 0x2090, "Configure devices -- dpc flags =0x%lx\n", flags); @@ -2279,7 +2279,6 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) struct sts_entry_fx00 *sts; __le16 comp_status; __le16 scsi_status; - uint16_t ox_id; __le16 lscsi_status; int32_t resid; uint32_t sense_len, par_sense_len, rsp_info_len, resid_len, @@ -2344,7 +2343,6 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) fcport = sp->fcport; - ox_id = 0; sense_len = par_sense_len = rsp_info_len = resid_len = fw_resid_len = 0; if (scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)) @@ -3071,7 +3069,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, int qlafx00_start_scsi(srb_t *sp) { - int ret, nseg; + int nseg; unsigned long flags; uint32_t index; uint32_t handle; @@ -3088,8 +3086,6 @@ qlafx00_start_scsi(srb_t *sp) struct scsi_lun llun; /* Setup device pointers. */ - ret = 0; - rsp = ha->rsp_q_map[0]; req = vha->req; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 47f8419adf41..5bc40d8dbb96 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1740,8 +1740,8 @@ qla82xx_pci_config(scsi_qla_host_t *vha) ret = pci_set_mwi(ha->pdev); ha->chip_revision = ha->pdev->revision; ql_dbg(ql_dbg_init, vha, 0x0043, - "Chip revision:%d.\n", - ha->chip_revision); + "Chip revision:%d; pci_set_mwi() returned %d.\n", + ha->chip_revision, ret); return 0; } @@ -2671,7 +2671,7 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr, { int ret; uint32_t liter; - uint32_t sec_mask, rest_addr; + uint32_t rest_addr; dma_addr_t optrom_dma; void *optrom = NULL; int page_mode = 0; @@ -2693,7 +2693,6 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr, } rest_addr = ha->fdt_block_size - 1; - sec_mask = ~rest_addr; ret = qla82xx_unprotect_flash(ha); if (ret) { @@ -2789,7 +2788,6 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; - struct device_reg_82xx __iomem *reg; uint32_t dbval; /* Adjust ring index. */ @@ -2800,7 +2798,6 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha) } else req->ring_ptr++; - reg = &ha->iobase->isp82; dbval = 0x04 | (ha->portnum << 5); dbval = dbval | (req->id << 8) | (req->ring_index << 16); diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index e06c851147d0..50e36f0348c1 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -462,12 +462,11 @@ qla8044_flash_lock(scsi_qla_host_t *vha) static void qla8044_flash_unlock(scsi_qla_host_t *vha) { - int ret_val; struct qla_hw_data *ha = vha->hw; /* Reading FLASH_UNLOCK register unlocks the Flash */ qla8044_wr_reg(ha, QLA8044_FLASH_LOCK_ID, 0xFF); - ret_val = qla8044_rd_reg(ha, QLA8044_FLASH_UNLOCK); + qla8044_rd_reg(ha, QLA8044_FLASH_UNLOCK); } @@ -2992,7 +2991,7 @@ qla8044_minidump_process_rddfe(struct scsi_qla_host *vha, uint32_t addr1, addr2, value, data, temp, wrVal; uint8_t stride, stride2; uint16_t count; - uint32_t poll, mask, data_size, modify_mask; + uint32_t poll, mask, modify_mask; uint32_t wait_count = 0; uint32_t *data_ptr = *d_ptr; @@ -3009,7 +3008,6 @@ qla8044_minidump_process_rddfe(struct scsi_qla_host *vha, poll = rddfe->poll; mask = rddfe->mask; modify_mask = rddfe->modify_mask; - data_size = rddfe->data_size; addr2 = addr1 + stride; @@ -3091,7 +3089,7 @@ qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha, uint8_t stride1, stride2; uint32_t addr3, addr4, addr5, addr6, addr7; uint16_t count, loop_cnt; - uint32_t poll, mask; + uint32_t mask; uint32_t *data_ptr = *d_ptr; struct qla8044_minidump_entry_rdmdio *rdmdio; @@ -3105,7 +3103,6 @@ qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha, stride2 = rdmdio->stride_2; count = rdmdio->count; - poll = rdmdio->poll; mask = rdmdio->mask; value2 = rdmdio->value_2; @@ -3164,7 +3161,7 @@ error: static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha, struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr) { - uint32_t addr1, addr2, value1, value2, poll, mask, r_value; + uint32_t addr1, addr2, value1, value2, poll, r_value; uint32_t wait_count = 0; struct qla8044_minidump_entry_pollwr *pollwr_hdr; @@ -3175,7 +3172,6 @@ static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha, value2 = pollwr_hdr->value_2; poll = pollwr_hdr->poll; - mask = pollwr_hdr->mask; while (wait_count < poll) { qla8044_rd_reg_indirect(vha, addr1, &r_value); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a28815b8276f..5a5166bd4287 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2973,7 +2973,6 @@ qla2x00_shutdown(struct pci_dev *pdev) static void qla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha) { - struct Scsi_Host *scsi_host; scsi_qla_host_t *vha; unsigned long flags; @@ -2984,7 +2983,7 @@ qla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha) BUG_ON(base_vha->list.next == &ha->vp_list); /* This assumes first entry in ha->vp_list is always base vha */ vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list); - scsi_host = scsi_host_get(vha->host); + scsi_host_get(vha->host); spin_unlock_irqrestore(&ha->vport_slock, flags); mutex_unlock(&ha->vport_lock); @@ -4793,7 +4792,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) static int qla2x00_do_dpc(void *data) { - int rval; scsi_qla_host_t *base_vha; struct qla_hw_data *ha; @@ -5025,7 +5023,7 @@ loop_resync_check: if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &base_vha->dpc_flags))) { - rval = qla2x00_loop_resync(base_vha); + qla2x00_loop_resync(base_vha); clear_bit(LOOP_RESYNC_ACTIVE, &base_vha->dpc_flags); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index b749026aa592..b635c05f829f 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2077,7 +2077,6 @@ static inline int qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) { uint32_t *cur_dsd; - int sgc; uint32_t transfer_length = 0; uint32_t data_bytes; uint32_t dif_bytes; @@ -2094,7 +2093,6 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) struct atio_from_isp *atio = &prm->cmd->atio; uint16_t t16; - sgc = 0; ha = vha->hw; pkt = (struct ctio_crc2_to_fw *)vha->req->ring_ptr; @@ -2563,7 +2561,7 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, /* Update protection tag */ if (cmd->prot_sg_cnt) { - uint32_t i, j = 0, k = 0, num_ent; + uint32_t i, k = 0, num_ent; struct scatterlist *sg, *sgl; @@ -2576,7 +2574,6 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, k += num_ent; continue; } - j = blocks_done - k - 1; k = blocks_done; break; } @@ -3063,7 +3060,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, { struct qla_hw_data *ha = vha->hw; struct se_cmd *se_cmd; - const struct target_core_fabric_ops *tfo; struct qla_tgt_cmd *cmd; if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) { @@ -3081,7 +3077,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, return; se_cmd = &cmd->se_cmd; - tfo = se_cmd->se_tfo; cmd->cmd_sent_to_fw = 0; qlt_unmap_sg(vha, cmd); @@ -3179,13 +3174,9 @@ skip_term: if (cmd->state == QLA_TGT_STATE_PROCESSED) { ; } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { - int rx_status = 0; - cmd->state = QLA_TGT_STATE_DATA_IN; - if (unlikely(status != CTIO_SUCCESS)) - rx_status = -EIO; - else + if (status == CTIO_SUCCESS) cmd->write_data_transferred = 1; ha->tgt.tgt_ops->handle_data(cmd); @@ -3580,12 +3571,11 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) struct qla_tgt *tgt; struct qla_tgt_sess *sess; uint32_t lun, unpacked_lun; - int lun_size, fn; + int fn; tgt = vha->vha_tgt.qla_tgt; lun = a->u.isp24.fcp_cmnd.lun; - lun_size = sizeof(a->u.isp24.fcp_cmnd.lun); fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, a->u.isp24.fcp_hdr.s_id); @@ -5044,7 +5034,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, uint8_t *s_id = NULL; /* to hide compiler warnings */ int rc; uint32_t lun, unpacked_lun; - int lun_size, fn; + int fn; void *iocb; spin_lock_irqsave(&ha->hardware_lock, flags); @@ -5071,7 +5061,6 @@ static void qlt_tmr_work(struct qla_tgt *tgt, iocb = a; lun = a->u.isp24.fcp_cmnd.lun; - lun_size = sizeof(lun); fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 962cb89fe0ae..7e876d1e2f78 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -805,9 +805,8 @@ static void qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) { uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; - int rval = 0; - rval = sscanf(qla2x00_version_str, "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", + sscanf(qla2x00_version_str, "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", v+0, v+1, v+2, v+3, v+4, v+5); tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; From df3f4cd0defd5f832a806ca1f0dd6638a2df17a5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:23:46 -0700 Subject: [PATCH 27/85] qla2xxx: Replace two macros with an inline function Replace the QLA82XX_ADDR_IN_RANGE() and QLA8044_ADDR_IN_RANGE() macros with the inline function addr_in_range(). This avoids that the compiler reports the following warning when building with W=1: comparison of unsigned expression >= 0 is always true. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 21 +++++++++------------ drivers/scsi/qla2xxx/qla_nx2.c | 4 ++-- drivers/scsi/qla2xxx/qla_nx2.h | 6 ++++-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 5bc40d8dbb96..89804d20c926 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -547,9 +547,6 @@ void qla82xx_idc_unlock(struct qla_hw_data *ha) qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); } -/* PCI Windowing for DDR regions. */ -#define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ - (((addr) <= (high)) && ((addr) >= (low))) /* * check memory access boundary. * used by test agent. support ddr access only for now @@ -558,9 +555,9 @@ static unsigned long qla82xx_pci_mem_bound_check(struct qla_hw_data *ha, unsigned long long addr, int size) { - if (!QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + if (!addr_in_range(addr, QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX) || - !QLA82XX_ADDR_IN_RANGE(addr + size - 1, QLA82XX_ADDR_DDR_NET, + !addr_in_range(addr + size - 1, QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX) || ((size != 1) && (size != 2) && (size != 4) && (size != 8))) return 0; @@ -577,7 +574,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) u32 win_read; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); - if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + if (addr_in_range(addr, QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX)) { /* DDR network side */ window = MN_WIN(addr); @@ -592,7 +589,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) __func__, window, win_read); } addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET; - } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, + } else if (addr_in_range(addr, QLA82XX_ADDR_OCM0, QLA82XX_ADDR_OCM0_MAX)) { unsigned int temp1; if ((addr & 0x00ff800) == 0xff800) { @@ -615,7 +612,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) } addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M; - } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, + } else if (addr_in_range(addr, QLA82XX_ADDR_QDR_NET, QLA82XX_P3_ADDR_QDR_NET_MAX)) { /* QDR network side */ window = MS_WIN(addr); @@ -656,16 +653,16 @@ static int qla82xx_pci_is_same_window(struct qla_hw_data *ha, qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX; /* DDR network side */ - if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + if (addr_in_range(addr, QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX)) BUG(); - else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, + else if (addr_in_range(addr, QLA82XX_ADDR_OCM0, QLA82XX_ADDR_OCM0_MAX)) return 1; - else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM1, + else if (addr_in_range(addr, QLA82XX_ADDR_OCM1, QLA82XX_ADDR_OCM1_MAX)) return 1; - else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, qdr_max)) { + else if (addr_in_range(addr, QLA82XX_ADDR_QDR_NET, qdr_max)) { /* QDR network side */ window = ((addr - QLA82XX_ADDR_QDR_NET) >> 22) & 0x3f; if (ha->qdr_sn_window == window) diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 50e36f0348c1..007192d7bad8 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -1129,9 +1129,9 @@ qla8044_ms_mem_write_128b(struct scsi_qla_host *vha, } for (i = 0; i < count; i++, addr += 16) { - if (!((QLA8044_ADDR_IN_RANGE(addr, QLA8044_ADDR_QDR_NET, + if (!((addr_in_range(addr, QLA8044_ADDR_QDR_NET, QLA8044_ADDR_QDR_NET_MAX)) || - (QLA8044_ADDR_IN_RANGE(addr, QLA8044_ADDR_DDR_NET, + (addr_in_range(addr, QLA8044_ADDR_DDR_NET, QLA8044_ADDR_DDR_NET_MAX)))) { ret_val = QLA_FUNCTION_FAILED; goto exit_ms_mem_write_unlock; diff --git a/drivers/scsi/qla2xxx/qla_nx2.h b/drivers/scsi/qla2xxx/qla_nx2.h index ada36057d7cd..02fe3c4cdf55 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.h +++ b/drivers/scsi/qla2xxx/qla_nx2.h @@ -58,8 +58,10 @@ #define QLA8044_PCI_QDR_NET_MAX ((unsigned long)0x043fffff) /* PCI Windowing for DDR regions. */ -#define QLA8044_ADDR_IN_RANGE(addr, low, high) \ - (((addr) <= (high)) && ((addr) >= (low))) +static inline bool addr_in_range(u64 addr, u64 low, u64 high) +{ + return addr <= high && addr >= low; +} /* Indirectly Mapped Registers */ #define QLA8044_FLASH_SPI_STATUS 0x2808E010 From ad950360eebb5f5f7610b13cfd08c0185ca3f146 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:24:08 -0700 Subject: [PATCH 28/85] qla2xxx: Remove __constant_ prefix Whether htonl() or __constant_htonl() is used, if the argument is a constant the conversion happens at compile time. Hence leave out the __constant_ prefix for this and other endianness conversion functions. This improves source code readability. [jejb: checkpatch fixes] Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 36 ++++---- drivers/scsi/qla2xxx/qla_gs.c | 52 +++++------ drivers/scsi/qla2xxx/qla_init.c | 143 ++++++++++++++---------------- drivers/scsi/qla2xxx/qla_iocb.c | 88 ++++++++---------- drivers/scsi/qla2xxx/qla_isr.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 25 +++--- drivers/scsi/qla2xxx/qla_mr.c | 2 +- drivers/scsi/qla2xxx/qla_nx.c | 6 +- drivers/scsi/qla2xxx/qla_sup.c | 14 +-- drivers/scsi/qla2xxx/qla_target.c | 116 ++++++++++++------------ 10 files changed, 231 insertions(+), 253 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 121ed5bdb4fa..3a786e4739ad 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -486,7 +486,7 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) return ptr; *last_chain = &fcec->type; - fcec->type = __constant_htonl(DUMP_CHAIN_FCE); + fcec->type = htonl(DUMP_CHAIN_FCE); fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) + fce_calc_size(ha->fce_bufs)); fcec->size = htonl(fce_calc_size(ha->fce_bufs)); @@ -527,7 +527,7 @@ qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr, /* aqp = ha->atio_q_map[que]; */ q = ptr; *last_chain = &q->type; - q->type = __constant_htonl(DUMP_CHAIN_QUEUE); + q->type = htonl(DUMP_CHAIN_QUEUE); q->chain_size = htonl( sizeof(struct qla2xxx_mqueue_chain) + sizeof(struct qla2xxx_mqueue_header) + @@ -536,7 +536,7 @@ qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr, /* Add header. */ qh = ptr; - qh->queue = __constant_htonl(TYPE_ATIO_QUEUE); + qh->queue = htonl(TYPE_ATIO_QUEUE); qh->number = htonl(que); qh->size = htonl(aqp->length * sizeof(request_t)); ptr += sizeof(struct qla2xxx_mqueue_header); @@ -571,7 +571,7 @@ qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) /* Add chain. */ q = ptr; *last_chain = &q->type; - q->type = __constant_htonl(DUMP_CHAIN_QUEUE); + q->type = htonl(DUMP_CHAIN_QUEUE); q->chain_size = htonl( sizeof(struct qla2xxx_mqueue_chain) + sizeof(struct qla2xxx_mqueue_header) + @@ -580,7 +580,7 @@ qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) /* Add header. */ qh = ptr; - qh->queue = __constant_htonl(TYPE_REQUEST_QUEUE); + qh->queue = htonl(TYPE_REQUEST_QUEUE); qh->number = htonl(que); qh->size = htonl(req->length * sizeof(request_t)); ptr += sizeof(struct qla2xxx_mqueue_header); @@ -599,7 +599,7 @@ qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) /* Add chain. */ q = ptr; *last_chain = &q->type; - q->type = __constant_htonl(DUMP_CHAIN_QUEUE); + q->type = htonl(DUMP_CHAIN_QUEUE); q->chain_size = htonl( sizeof(struct qla2xxx_mqueue_chain) + sizeof(struct qla2xxx_mqueue_header) + @@ -608,7 +608,7 @@ qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) /* Add header. */ qh = ptr; - qh->queue = __constant_htonl(TYPE_RESPONSE_QUEUE); + qh->queue = htonl(TYPE_RESPONSE_QUEUE); qh->number = htonl(que); qh->size = htonl(rsp->length * sizeof(response_t)); ptr += sizeof(struct qla2xxx_mqueue_header); @@ -634,8 +634,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) mq = ptr; *last_chain = &mq->type; - mq->type = __constant_htonl(DUMP_CHAIN_MQ); - mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain)); + mq->type = htonl(DUMP_CHAIN_MQ); + mq->chain_size = htonl(sizeof(struct qla2xxx_mq_chain)); que_cnt = ha->max_req_queues > ha->max_rsp_queues ? ha->max_req_queues : ha->max_rsp_queues; @@ -1271,8 +1271,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) nxt_chain = (void *)ha->fw_dump + ha->chain_offset; nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); - *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT); + *last_chain |= htonl(DUMP_CHAIN_LAST); } /* Adjust valid length. */ @@ -1323,7 +1323,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } fw = &ha->fw_dump->isp.isp25; qla2xxx_prep_dump(ha, ha->fw_dump); - ha->fw_dump->version = __constant_htonl(2); + ha->fw_dump->version = htonl(2); fw->host_status = htonl(RD_REG_DWORD(®->host_status)); @@ -1587,8 +1587,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); - *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT); + *last_chain |= htonl(DUMP_CHAIN_LAST); } /* Adjust valid length. */ @@ -1905,8 +1905,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); - *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT); + *last_chain |= htonl(DUMP_CHAIN_LAST); } /* Adjust valid length. */ @@ -2408,8 +2408,8 @@ copy_queue: nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); - *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT); + *last_chain |= htonl(DUMP_CHAIN_LAST); } /* Adjust valid length. */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index dccc4dcc39c8..94e8a8592f69 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -35,10 +35,10 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size) ms_pkt->entry_type = MS_IOCB_TYPE; ms_pkt->entry_count = 1; SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER); - ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); + ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG); ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); - ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); - ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); + ms_pkt->cmd_dsd_count = cpu_to_le16(1); + ms_pkt->total_dsd_count = cpu_to_le16(2); ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); ms_pkt->req_bytecount = cpu_to_le32(req_size); @@ -74,10 +74,10 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size) ct_pkt->entry_type = CT_IOCB_TYPE; ct_pkt->entry_count = 1; - ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS); + ct_pkt->nport_handle = cpu_to_le16(NPH_SNS); ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); - ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); - ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); + ct_pkt->cmd_dsd_count = cpu_to_le16(1); + ct_pkt->rsp_dsd_count = cpu_to_le16(1); ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size); @@ -142,7 +142,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt, case CS_DATA_UNDERRUN: case CS_DATA_OVERRUN: /* Overrun? */ if (ct_rsp->header.response != - __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { + cpu_to_be16(CT_ACCEPT_RESPONSE)) { ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077, "%s failed rejected request on port_id: %02x%02x%02x Compeltion status 0x%x, response 0x%x\n", routine, vha->d_id.b.domain, @@ -1153,10 +1153,10 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, ms_pkt->entry_type = MS_IOCB_TYPE; ms_pkt->entry_count = 1; SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id); - ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); + ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG); ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); - ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); - ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); + ms_pkt->cmd_dsd_count = cpu_to_le16(1); + ms_pkt->total_dsd_count = cpu_to_le16(2); ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); ms_pkt->req_bytecount = cpu_to_le32(req_size); @@ -1193,8 +1193,8 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, ct_pkt->entry_count = 1; ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id); ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); - ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); - ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); + ct_pkt->cmd_dsd_count = cpu_to_le16(1); + ct_pkt->rsp_dsd_count = cpu_to_le16(1); ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size); @@ -1281,19 +1281,19 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Prepare FDMI command arguments -- attribute block, attributes. */ memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1); + ct_req->req.rhba.entry_count = cpu_to_be32(1); memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE); size = 2 * WWN_SIZE + 4 + 4; /* Attributes */ ct_req->req.rhba.attrs.count = - __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT); + cpu_to_be32(FDMI_HBA_ATTR_COUNT); entries = ct_req->req.rhba.hba_identifier; /* Nodename. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE); + eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); + eiter->len = cpu_to_be16(4 + WWN_SIZE); memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); size += 4 + WWN_SIZE; @@ -1302,7 +1302,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Manufacturer. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER); + eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); alen = strlen(QLA2XXX_MANUFACTURER); snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), "%s", "QLogic Corporation"); @@ -1315,7 +1315,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Serial number. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); + eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); if (IS_FWI2_CAPABLE(ha)) qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, sizeof(eiter->a.serial_num)); @@ -1335,7 +1335,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Model name. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL); + eiter->type = cpu_to_be16(FDMI_HBA_MODEL); snprintf(eiter->a.model, sizeof(eiter->a.model), "%s", ha->model_number); alen = strlen(eiter->a.model); @@ -1348,7 +1348,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Model description. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); + eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), "%s", ha->model_desc); alen = strlen(eiter->a.model_desc); @@ -1361,7 +1361,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Hardware version. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); + eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); if (!IS_FWI2_CAPABLE(ha)) { snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), "HW:%s", ha->adapter_id); @@ -1385,7 +1385,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Driver version. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION); + eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), "%s", qla2x00_version_str); alen = strlen(eiter->a.driver_version); @@ -1398,7 +1398,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Option ROM version. */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); + eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); alen = strlen(eiter->a.orom_version); @@ -1411,7 +1411,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Firmware version */ eiter = entries + size; - eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); + eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, sizeof(eiter->a.fw_version)); alen = strlen(eiter->a.fw_version); @@ -2484,8 +2484,8 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size, ct_pkt->entry_count = 1; ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id); ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); - ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); - ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); + ct_pkt->cmd_dsd_count = cpu_to_le16(1); + ct_pkt->rsp_dsd_count = cpu_to_le16(1); ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f4a64a4fc40a..ceced7ff8083 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1685,7 +1685,7 @@ allocate: ha->fw_dump->signature[1] = 'L'; ha->fw_dump->signature[2] = 'G'; ha->fw_dump->signature[3] = 'C'; - ha->fw_dump->version = __constant_htonl(1); + ha->fw_dump->version = htonl(1); ha->fw_dump->fixed_size = htonl(fixed_size); ha->fw_dump->mem_size = htonl(mem_size); @@ -2065,8 +2065,8 @@ qla2x00_config_rings(struct scsi_qla_host *vha) struct rsp_que *rsp = ha->rsp_q_map[0]; /* Setup ring parameters in initialization control block. */ - ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); - ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); + ha->init_cb->request_q_outpointer = cpu_to_le16(0); + ha->init_cb->response_q_inpointer = cpu_to_le16(0); ha->init_cb->request_q_length = cpu_to_le16(req->length); ha->init_cb->response_q_length = cpu_to_le16(rsp->length); ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); @@ -2095,8 +2095,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha) /* Setup ring parameters in initialization control block. */ icb = (struct init_cb_24xx *)ha->init_cb; - icb->request_q_outpointer = __constant_cpu_to_le16(0); - icb->response_q_inpointer = __constant_cpu_to_le16(0); + icb->request_q_outpointer = cpu_to_le16(0); + icb->response_q_inpointer = cpu_to_le16(0); icb->request_q_length = cpu_to_le16(req->length); icb->response_q_length = cpu_to_le16(rsp->length); icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); @@ -2105,18 +2105,17 @@ qla24xx_config_rings(struct scsi_qla_host *vha) icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); /* Setup ATIO queue dma pointers for target mode */ - icb->atio_q_inpointer = __constant_cpu_to_le16(0); + icb->atio_q_inpointer = cpu_to_le16(0); icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length); icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); if (IS_SHADOW_REG_CAPABLE(ha)) - icb->firmware_options_2 |= - __constant_cpu_to_le32(BIT_30|BIT_29); + icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29); if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { - icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); - icb->rid = __constant_cpu_to_le16(rid); + icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS); + icb->rid = cpu_to_le16(rid); if (ha->flags.msix_enabled) { msix = &ha->msix_entries[1]; ql_dbg(ql_dbg_init, vha, 0x00fd, @@ -2126,26 +2125,22 @@ qla24xx_config_rings(struct scsi_qla_host *vha) } /* Use alternate PCI bus number */ if (MSB(rid)) - icb->firmware_options_2 |= - __constant_cpu_to_le32(BIT_19); + icb->firmware_options_2 |= cpu_to_le32(BIT_19); /* Use alternate PCI devfn */ if (LSB(rid)) - icb->firmware_options_2 |= - __constant_cpu_to_le32(BIT_18); + icb->firmware_options_2 |= cpu_to_le32(BIT_18); /* Use Disable MSIX Handshake mode for capable adapters */ if ((ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) && (ha->flags.msix_enabled)) { - icb->firmware_options_2 &= - __constant_cpu_to_le32(~BIT_22); + icb->firmware_options_2 &= cpu_to_le32(~BIT_22); ha->flags.disable_msix_handshake = 1; ql_dbg(ql_dbg_init, vha, 0x00fe, "MSIX Handshake Disable Mode turned on.\n"); } else { - icb->firmware_options_2 |= - __constant_cpu_to_le32(BIT_22); + icb->firmware_options_2 |= cpu_to_le32(BIT_22); } - icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23); + icb->firmware_options_2 |= cpu_to_le32(BIT_23); WRT_REG_DWORD(®->isp25mq.req_q_in, 0); WRT_REG_DWORD(®->isp25mq.req_q_out, 0); @@ -2243,7 +2238,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha) } if (IS_FWI2_CAPABLE(ha)) { - mid_init_cb->options = __constant_cpu_to_le16(BIT_1); + mid_init_cb->options = cpu_to_le16(BIT_1); mid_init_cb->init_cb.execution_throttle = cpu_to_le16(ha->fw_xcb_count); /* D-Port Status */ @@ -2672,8 +2667,8 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv->frame_payload_size = 1024; } - nv->max_iocb_allocation = __constant_cpu_to_le16(256); - nv->execution_throttle = __constant_cpu_to_le16(16); + nv->max_iocb_allocation = cpu_to_le16(256); + nv->execution_throttle = cpu_to_le16(16); nv->retry_count = 8; nv->retry_delay = 1; @@ -2691,7 +2686,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv->host_p[1] = BIT_2; nv->reset_delay = 5; nv->port_down_retry_count = 8; - nv->max_luns_per_target = __constant_cpu_to_le16(8); + nv->max_luns_per_target = cpu_to_le16(8); nv->link_down_timeout = 60; rval = 1; @@ -2819,7 +2814,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) memcpy(vha->node_name, icb->node_name, WWN_SIZE); memcpy(vha->port_name, icb->port_name, WWN_SIZE); - icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + icb->execution_throttle = cpu_to_le16(0xFFFF); ha->retry_count = nv->retry_count; @@ -2871,10 +2866,10 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) if (ql2xloginretrycount) ha->login_retry_count = ql2xloginretrycount; - icb->lun_enables = __constant_cpu_to_le16(0); + icb->lun_enables = cpu_to_le16(0); icb->command_resource_count = 0; icb->immediate_notify_resource_count = 0; - icb->timeout = __constant_cpu_to_le16(0); + icb->timeout = cpu_to_le16(0); if (IS_QLA2100(ha) || IS_QLA2200(ha)) { /* Enable RIO */ @@ -5005,7 +5000,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || - nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { + nv->nvram_version < cpu_to_le16(ICB_VERSION)) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x006b, "Inconsistent NVRAM detected: checksum=0x%x id=%c " @@ -5018,12 +5013,12 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) * Set default initialization control block. */ memset(nv, 0, ha->nvram_size); - nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); - nv->version = __constant_cpu_to_le16(ICB_VERSION); + nv->nvram_version = cpu_to_le16(ICB_VERSION); + nv->version = cpu_to_le16(ICB_VERSION); nv->frame_payload_size = 2048; - nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); - nv->exchange_count = __constant_cpu_to_le16(0); - nv->hard_address = __constant_cpu_to_le16(124); + nv->execution_throttle = cpu_to_le16(0xFFFF); + nv->exchange_count = cpu_to_le16(0); + nv->hard_address = cpu_to_le16(124); nv->port_name[0] = 0x21; nv->port_name[1] = 0x00 + ha->port_no + 1; nv->port_name[2] = 0x00; @@ -5041,29 +5036,29 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) nv->node_name[6] = 0x55; nv->node_name[7] = 0x86; qla24xx_nvram_wwn_from_ofw(vha, nv); - nv->login_retry_count = __constant_cpu_to_le16(8); - nv->interrupt_delay_timer = __constant_cpu_to_le16(0); - nv->login_timeout = __constant_cpu_to_le16(0); + nv->login_retry_count = cpu_to_le16(8); + nv->interrupt_delay_timer = cpu_to_le16(0); + nv->login_timeout = cpu_to_le16(0); nv->firmware_options_1 = - __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); - nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); - nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); - nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); - nv->efi_parameters = __constant_cpu_to_le32(0); + cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); + nv->firmware_options_2 = cpu_to_le32(2 << 4); + nv->firmware_options_2 |= cpu_to_le32(BIT_12); + nv->firmware_options_3 = cpu_to_le32(2 << 13); + nv->host_p = cpu_to_le32(BIT_11|BIT_10); + nv->efi_parameters = cpu_to_le32(0); nv->reset_delay = 5; - nv->max_luns_per_target = __constant_cpu_to_le16(128); - nv->port_down_retry_count = __constant_cpu_to_le16(30); - nv->link_down_timeout = __constant_cpu_to_le16(30); + nv->max_luns_per_target = cpu_to_le16(128); + nv->port_down_retry_count = cpu_to_le16(30); + nv->link_down_timeout = cpu_to_le16(30); rval = 1; } if (!qla_ini_mode_enabled(vha)) { /* Don't enable full login after initial LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); + nv->firmware_options_1 &= cpu_to_le32(~BIT_13); /* Don't enable LIP full login for initiator */ - nv->host_p &= __constant_cpu_to_le32(~BIT_10); + nv->host_p &= cpu_to_le32(~BIT_10); } qlt_24xx_config_nvram_stage1(vha, nv); @@ -5097,14 +5092,14 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) qlt_24xx_config_nvram_stage2(vha, icb); - if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { + if (nv->host_p & cpu_to_le32(BIT_15)) { /* Use alternate WWN? */ memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); } /* Prepare nodename */ - if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { + if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. @@ -5136,7 +5131,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) memcpy(vha->node_name, icb->node_name, WWN_SIZE); memcpy(vha->port_name, icb->port_name, WWN_SIZE); - icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + icb->execution_throttle = cpu_to_le16(0xFFFF); ha->retry_count = le16_to_cpu(nv->login_retry_count); @@ -5144,7 +5139,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout) nv->login_timeout = cpu_to_le16(ql2xlogintimeout); if (le16_to_cpu(nv->login_timeout) < 4) - nv->login_timeout = __constant_cpu_to_le16(4); + nv->login_timeout = cpu_to_le16(4); ha->login_timeout = le16_to_cpu(nv->login_timeout); icb->login_timeout = nv->login_timeout; @@ -5195,7 +5190,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? le16_to_cpu(icb->interrupt_delay_timer): 2; } - icb->firmware_options_2 &= __constant_cpu_to_le32( + icb->firmware_options_2 &= cpu_to_le32( ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); vha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { @@ -5951,7 +5946,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || - nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { + nv->nvram_version < cpu_to_le16(ICB_VERSION)) { /* Reset NVRAM data. */ ql_log(ql_log_info, vha, 0x0073, "Inconsistent NVRAM detected: checksum=0x%x id=%c " @@ -5965,11 +5960,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) * Set default initialization control block. */ memset(nv, 0, ha->nvram_size); - nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); - nv->version = __constant_cpu_to_le16(ICB_VERSION); + nv->nvram_version = cpu_to_le16(ICB_VERSION); + nv->version = cpu_to_le16(ICB_VERSION); nv->frame_payload_size = 2048; - nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); - nv->exchange_count = __constant_cpu_to_le16(0); + nv->execution_throttle = cpu_to_le16(0xFFFF); + nv->exchange_count = cpu_to_le16(0); nv->port_name[0] = 0x21; nv->port_name[1] = 0x00 + ha->port_no + 1; nv->port_name[2] = 0x00; @@ -5986,20 +5981,20 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) nv->node_name[5] = 0x1c; nv->node_name[6] = 0x55; nv->node_name[7] = 0x86; - nv->login_retry_count = __constant_cpu_to_le16(8); - nv->interrupt_delay_timer = __constant_cpu_to_le16(0); - nv->login_timeout = __constant_cpu_to_le16(0); + nv->login_retry_count = cpu_to_le16(8); + nv->interrupt_delay_timer = cpu_to_le16(0); + nv->login_timeout = cpu_to_le16(0); nv->firmware_options_1 = - __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); - nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); - nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); - nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); - nv->efi_parameters = __constant_cpu_to_le32(0); + cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); + nv->firmware_options_2 = cpu_to_le32(2 << 4); + nv->firmware_options_2 |= cpu_to_le32(BIT_12); + nv->firmware_options_3 = cpu_to_le32(2 << 13); + nv->host_p = cpu_to_le32(BIT_11|BIT_10); + nv->efi_parameters = cpu_to_le32(0); nv->reset_delay = 5; - nv->max_luns_per_target = __constant_cpu_to_le16(128); - nv->port_down_retry_count = __constant_cpu_to_le16(30); - nv->link_down_timeout = __constant_cpu_to_le16(180); + nv->max_luns_per_target = cpu_to_le16(128); + nv->port_down_retry_count = cpu_to_le16(30); + nv->link_down_timeout = cpu_to_le16(180); nv->enode_mac[0] = 0x00; nv->enode_mac[1] = 0xC0; nv->enode_mac[2] = 0xDD; @@ -6058,13 +6053,13 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) qlt_81xx_config_nvram_stage2(vha, icb); /* Use alternate WWN? */ - if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { + if (nv->host_p & cpu_to_le32(BIT_15)) { memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); } /* Prepare nodename */ - if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { + if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. @@ -6093,7 +6088,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) memcpy(vha->node_name, icb->node_name, WWN_SIZE); memcpy(vha->port_name, icb->port_name, WWN_SIZE); - icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + icb->execution_throttle = cpu_to_le16(0xFFFF); ha->retry_count = le16_to_cpu(nv->login_retry_count); @@ -6101,7 +6096,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout) nv->login_timeout = cpu_to_le16(ql2xlogintimeout); if (le16_to_cpu(nv->login_timeout) < 4) - nv->login_timeout = __constant_cpu_to_le16(4); + nv->login_timeout = cpu_to_le16(4); ha->login_timeout = le16_to_cpu(nv->login_timeout); icb->login_timeout = nv->login_timeout; @@ -6147,7 +6142,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) /* if not running MSI-X we need handshaking on interrupts */ if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha))) - icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22); + icb->firmware_options_2 |= cpu_to_le32(BIT_22); /* Enable ZIO. */ if (!vha->flags.init_done) { @@ -6156,7 +6151,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? le16_to_cpu(icb->interrupt_delay_timer): 2; } - icb->firmware_options_2 &= __constant_cpu_to_le32( + icb->firmware_options_2 &= cpu_to_le32( ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); vha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index e95162e1fcb7..fbb1fe9fd357 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -108,8 +108,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) cont_pkt = (cont_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&cont_pkt->entry_type)) = - __constant_cpu_to_le32(CONTINUE_TYPE); + *((uint32_t *)(&cont_pkt->entry_type)) = cpu_to_le32(CONTINUE_TYPE); return (cont_pkt); } @@ -138,8 +137,8 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) /* Load packet defaults. */ *((uint32_t *)(&cont_pkt->entry_type)) = IS_QLAFX00(vha->hw) ? - __constant_cpu_to_le32(CONTINUE_A64_TYPE_FX00) : - __constant_cpu_to_le32(CONTINUE_A64_TYPE); + cpu_to_le32(CONTINUE_A64_TYPE_FX00) : + cpu_to_le32(CONTINUE_A64_TYPE); return (cont_pkt); } @@ -204,11 +203,11 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, /* Update entry type to indicate Command Type 2 IOCB */ *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_TYPE); + cpu_to_le32(COMMAND_TYPE); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return; } @@ -261,12 +260,11 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_A64_TYPE); + *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_A64_TYPE); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return; } @@ -402,7 +400,7 @@ qla2x00_start_scsi(srb_t *sp) /* Set target ID and LUN number*/ SET_TARGET_ID(ha, cmd_pkt->target, sp->fcport->loop_id); cmd_pkt->lun = cpu_to_le16(cmd->device->lun); - cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); + cmd_pkt->control_flags = cpu_to_le16(CF_SIMPLE_TAG); /* Load SCSI command packet. */ memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len); @@ -596,12 +594,11 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_TYPE_6); + *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_6); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return 0; } @@ -610,13 +607,11 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { - cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_WRITE_DATA); + cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA); vha->qla_stats.output_bytes += scsi_bufflen(cmd); vha->qla_stats.output_requests++; } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_READ_DATA); + cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA); vha->qla_stats.input_bytes += scsi_bufflen(cmd); vha->qla_stats.input_requests++; } @@ -713,12 +708,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_TYPE_7); + *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_7); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return; } @@ -726,13 +720,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { - cmd_pkt->task_mgmt_flags = - __constant_cpu_to_le16(TMF_WRITE_DATA); + cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_WRITE_DATA); vha->qla_stats.output_bytes += scsi_bufflen(cmd); vha->qla_stats.output_requests++; } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - cmd_pkt->task_mgmt_flags = - __constant_cpu_to_le16(TMF_READ_DATA); + cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_READ_DATA); vha->qla_stats.input_bytes += scsi_bufflen(cmd); vha->qla_stats.input_requests++; } @@ -806,7 +798,7 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, * match LBA in CDB + N */ case SCSI_PROT_DIF_TYPE2: - pkt->app_tag = __constant_cpu_to_le16(0); + pkt->app_tag = cpu_to_le16(0); pkt->app_tag_mask[0] = 0x0; pkt->app_tag_mask[1] = 0x0; @@ -837,7 +829,7 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, case SCSI_PROT_DIF_TYPE1: pkt->ref_tag = cpu_to_le32((uint32_t) (0xffffffff & scsi_get_lba(cmd))); - pkt->app_tag = __constant_cpu_to_le16(0); + pkt->app_tag = cpu_to_le16(0); pkt->app_tag_mask[0] = 0x0; pkt->app_tag_mask[1] = 0x0; @@ -1238,8 +1230,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type CRC_2 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_TYPE_CRC_2); + *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2); vha = sp->fcport->vha; ha = vha->hw; @@ -1247,7 +1238,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, /* No data transfer */ data_bytes = scsi_bufflen(cmd); if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return QLA_SUCCESS; } @@ -1256,10 +1247,10 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_WRITE_DATA); + cpu_to_le16(CF_WRITE_DATA); } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_READ_DATA); + cpu_to_le16(CF_READ_DATA); } if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) || @@ -1381,7 +1372,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, crc_ctx_pkt->blk_size = cpu_to_le16(blk_size); crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts); crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); - crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0); + crc_ctx_pkt->guard_seed = cpu_to_le16(0); /* Fibre channel byte count */ cmd_pkt->byte_count = cpu_to_le32(total_bytes); fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 + @@ -1389,13 +1380,12 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, *fcp_dl = htonl(total_bytes); if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); + cmd_pkt->byte_count = cpu_to_le32(0); return QLA_SUCCESS; } /* Walks data segments */ - cmd_pkt->control_flags |= - __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); + cmd_pkt->control_flags |= cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); if (!bundling && tot_prot_dsds) { if (qla24xx_walk_and_build_sglist_no_difb(ha, sp, @@ -1407,8 +1397,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, if (bundling && tot_prot_dsds) { /* Walks dif segments */ - cmd_pkt->control_flags |= - __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); + cmd_pkt->control_flags |= cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd, tot_prot_dsds, NULL)) @@ -1740,7 +1729,7 @@ qla24xx_dif_start_scsi(srb_t *sp) cmd_pkt->entry_count = (uint8_t)req_cnt; /* Specify response queue number where completion should happen */ cmd_pkt->entry_status = (uint8_t) rsp->id; - cmd_pkt->timeout = __constant_cpu_to_le16(0); + cmd_pkt->timeout = cpu_to_le16(0); wmb(); /* Adjust ring index. */ @@ -2028,10 +2017,10 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->entry_status = 0; els_iocb->handle = sp->handle; els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); - els_iocb->tx_dsd_count = __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); + els_iocb->tx_dsd_count = cpu_to_le16(bsg_job->request_payload.sg_cnt); els_iocb->vp_index = sp->fcport->vha->vp_idx; els_iocb->sof_type = EST_SOFI3; - els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); + els_iocb->rx_dsd_count = cpu_to_le16(bsg_job->reply_payload.sg_cnt); els_iocb->opcode = sp->type == SRB_ELS_CMD_RPT ? @@ -2082,13 +2071,13 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) ct_iocb->entry_status = 0; ct_iocb->handle1 = sp->handle; SET_TARGET_ID(ha, ct_iocb->loop_id, sp->fcport->loop_id); - ct_iocb->status = __constant_cpu_to_le16(0); - ct_iocb->control_flags = __constant_cpu_to_le16(0); + ct_iocb->status = cpu_to_le16(0); + ct_iocb->control_flags = cpu_to_le16(0); ct_iocb->timeout = 0; ct_iocb->cmd_dsd_count = - __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); + cpu_to_le16(bsg_job->request_payload.sg_cnt); ct_iocb->total_dsd_count = - __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt + 1); + cpu_to_le16(bsg_job->request_payload.sg_cnt + 1); ct_iocb->req_bytecount = cpu_to_le32(bsg_job->request_payload.payload_len); ct_iocb->rsp_bytecount = @@ -2161,13 +2150,13 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); ct_iocb->vp_index = sp->fcport->vha->vp_idx; - ct_iocb->comp_status = __constant_cpu_to_le16(0); + ct_iocb->comp_status = cpu_to_le16(0); ct_iocb->cmd_dsd_count = - __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); + cpu_to_le16(bsg_job->request_payload.sg_cnt); ct_iocb->timeout = 0; ct_iocb->rsp_dsd_count = - __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); + cpu_to_le16(bsg_job->reply_payload.sg_cnt); ct_iocb->rsp_byte_count = cpu_to_le32(bsg_job->reply_payload.payload_len); ct_iocb->cmd_byte_count = @@ -2661,7 +2650,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, /*Update entry type to indicate bidir command */ *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_BIDIRECTIONAL); + cpu_to_le32(COMMAND_BIDIRECTIONAL); /* Set the transfer direction, in this set both flags * Also set the BD_WRAP_BACK flag, firmware will take care @@ -2669,8 +2658,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, */ cmd_pkt->wr_dseg_count = cpu_to_le16(bsg_job->request_payload.sg_cnt); cmd_pkt->rd_dseg_count = cpu_to_le16(bsg_job->reply_payload.sg_cnt); - cmd_pkt->control_flags = - __constant_cpu_to_le16(BD_WRITE_DATA | BD_READ_DATA | + cmd_pkt->control_flags = cpu_to_le16(BD_WRITE_DATA | BD_READ_DATA | BD_WRAP_BACK); req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a526c389fa2f..2cb0fba38c9e 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1564,7 +1564,7 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) "Async-%s error - hdl=%x entry-status(%x).\n", type, sp->handle, sts->entry_status); iocb->u.tmf.data = QLA_FUNCTION_FAILED; - } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_log(ql_log_warn, fcport->vha, 0x5039, "Async-%s error - hdl=%x completion status(%x).\n", type, sp->handle, sts->comp_status); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 65c2dc1e929a..0c5477f1bfba 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1886,11 +1886,11 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->entry_count = 1; lg->handle = MAKE_HANDLE(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); - lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI); + lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); if (opt & BIT_0) - lg->control_flags |= __constant_cpu_to_le16(LCF_COND_PLOGI); + lg->control_flags |= cpu_to_le16(LCF_COND_PLOGI); if (opt & BIT_1) - lg->control_flags |= __constant_cpu_to_le16(LCF_SKIP_PRLI); + lg->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); lg->port_id[0] = al_pa; lg->port_id[1] = area; lg->port_id[2] = domain; @@ -1905,7 +1905,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, "Failed to complete IOCB -- error status (%x).\n", lg->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) { iop[0] = le32_to_cpu(lg->io_parameter[0]); iop[1] = le32_to_cpu(lg->io_parameter[1]); @@ -1959,7 +1959,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, mb[10] |= BIT_0; /* Class 2. */ if (lg->io_parameter[9] || lg->io_parameter[10]) mb[10] |= BIT_1; /* Class 3. */ - if (lg->io_parameter[0] & __constant_cpu_to_le32(BIT_7)) + if (lg->io_parameter[0] & cpu_to_le32(BIT_7)) mb[10] |= BIT_7; /* Confirmed Completion * Allowed */ @@ -2161,7 +2161,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->handle = MAKE_HANDLE(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = - __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| + cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| LCF_FREE_NPORT); lg->port_id[0] = al_pa; lg->port_id[1] = area; @@ -2177,7 +2177,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, "Failed to complete IOCB -- error status (%x).\n", lg->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_dbg(ql_dbg_mbx, vha, 0x1071, "Failed to complete IOCB -- completion status (%x) " "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status), @@ -2668,7 +2668,7 @@ qla24xx_abort_command(srb_t *sp) "Failed to complete IOCB -- error status (%x).\n", abt->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (abt->nport_handle != __constant_cpu_to_le16(0)) { + } else if (abt->nport_handle != cpu_to_le16(0)) { ql_dbg(ql_dbg_mbx, vha, 0x1090, "Failed to complete IOCB -- completion status (%x).\n", le16_to_cpu(abt->nport_handle)); @@ -2751,8 +2751,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, "Failed to complete IOCB -- error status (%x).\n", sts->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (sts->comp_status != - __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_dbg(ql_dbg_mbx, vha, 0x1096, "Failed to complete IOCB -- completion status (%x).\n", le16_to_cpu(sts->comp_status)); @@ -3478,7 +3477,7 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) "Failed to complete IOCB -- error status (%x).\n", vpmod->comp_status); rval = QLA_FUNCTION_FAILED; - } else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (vpmod->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_dbg(ql_dbg_mbx, vha, 0x10bf, "Failed to complete IOCB -- completion status (%x).\n", le16_to_cpu(vpmod->comp_status)); @@ -3537,7 +3536,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) vce->entry_type = VP_CTRL_IOCB_TYPE; vce->entry_count = 1; vce->command = cpu_to_le16(cmd); - vce->vp_count = __constant_cpu_to_le16(1); + vce->vp_count = cpu_to_le16(1); /* index map in firmware starts with 1; decrement index * this is ok as we never use index 0 @@ -3557,7 +3556,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) "Failed to complete IOCB -- error status (%x).\n", vce->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { + } else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_dbg(ql_dbg_mbx, vha, 0x10c5, "Failed to complet IOCB -- completion status (%x).\n", le16_to_cpu(vce->comp_status)); diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 1843ba91e2c8..2d798e6fadb3 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -3007,7 +3007,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - lcmd_pkt->byte_count = __constant_cpu_to_le32(0); + lcmd_pkt->byte_count = cpu_to_le32(0); return; } diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 89804d20c926..264be49d0490 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1765,8 +1765,8 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) /* Setup ring parameters in initialization control block. */ icb = (struct init_cb_81xx *)ha->init_cb; - icb->request_q_outpointer = __constant_cpu_to_le16(0); - icb->response_q_inpointer = __constant_cpu_to_le16(0); + icb->request_q_outpointer = cpu_to_le16(0); + icb->response_q_inpointer = cpu_to_le16(0); icb->request_q_length = cpu_to_le16(req->length); icb->response_q_length = cpu_to_le16(rsp->length); icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); @@ -2546,7 +2546,7 @@ qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, "Do ROM fast read failed.\n"); goto done_read; } - dwptr[i] = __constant_cpu_to_le32(val); + dwptr[i] = cpu_to_le32(val); } done_read: return dwptr; diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 028e8c8a7de9..e44d54231cdc 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -316,7 +316,7 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha) wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base, - __constant_cpu_to_le16(0x1234), 100000); + cpu_to_le16(0x1234), 100000); wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); if (stat != QLA_SUCCESS || wprot != 0x1234) { /* Write enable. */ @@ -691,9 +691,9 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) region = (struct qla_flt_region *)&flt[1]; ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, flt_addr << 2, OPTROM_BURST_SIZE); - if (*wptr == __constant_cpu_to_le16(0xffff)) + if (*wptr == cpu_to_le16(0xffff)) goto no_flash_data; - if (flt->version != __constant_cpu_to_le16(1)) { + if (flt->version != cpu_to_le16(1)) { ql_log(ql_log_warn, vha, 0x0047, "Unsupported FLT detected: version=0x%x length=0x%x checksum=0x%x.\n", le16_to_cpu(flt->version), le16_to_cpu(flt->length), @@ -892,7 +892,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) fdt = (struct qla_fdt_layout *)req->ring; ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); - if (*wptr == __constant_cpu_to_le16(0xffff)) + if (*wptr == cpu_to_le16(0xffff)) goto no_flash_data; if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || fdt->sig[3] != 'D') @@ -991,7 +991,7 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha) ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, QLA82XX_IDC_PARAM_ADDR , 8); - if (*wptr == __constant_cpu_to_le32(0xffffffff)) { + if (*wptr == cpu_to_le32(0xffffffff)) { ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT; ha->fcoe_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT; } else { @@ -1051,9 +1051,9 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr, ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); - if (hdr.version == __constant_cpu_to_le16(0xffff)) + if (hdr.version == cpu_to_le16(0xffff)) return; - if (hdr.version != __constant_cpu_to_le16(1)) { + if (hdr.version != cpu_to_le16(1)) { ql_dbg(ql_dbg_user, vha, 0x7090, "Unsupported NPIV-Config " "detected: version=0x%x entries=0x%x checksum=0x%x.\n", diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index b635c05f829f..445af44c9a7a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1023,7 +1023,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha, nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { nack->u.isp24.flags = ntfy->u.isp24.flags & - __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); + cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); } nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; nack->u.isp24.status = ntfy->u.isp24.status; @@ -1081,7 +1081,7 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, resp->sof_type = abts->sof_type; resp->exchange_address = abts->exchange_address; resp->fcp_hdr_le = abts->fcp_hdr_le; - f_ctl = __constant_cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP | + f_ctl = cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP | F_CTL_LAST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE); p = (uint8_t *)&f_ctl; @@ -1156,15 +1156,14 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, ctio->entry_count = 1; ctio->nport_handle = entry->nport_handle; ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; - ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio->vp_index = vha->vp_idx; ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0]; ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1]; ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2]; ctio->exchange_addr = entry->exchange_addr_to_abort; - ctio->u.status1.flags = - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_TERMINATE); + ctio->u.status1.flags = cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | + CTIO7_FLAGS_TERMINATE); ctio->u.status1.ox_id = cpu_to_le16(entry->fcp_hdr_le.ox_id); /* Memory Barrier */ @@ -1324,20 +1323,19 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, ctio->entry_count = 1; ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; ctio->nport_handle = mcmd->sess->loop_id; - ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio->vp_index = ha->vp_idx; ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio->exchange_addr = atio->u.isp24.exchange_addr; ctio->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_SEND_STATUS); + cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio->u.status1.ox_id = cpu_to_le16(temp); ctio->u.status1.scsi_status = - __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); - ctio->u.status1.response_len = __constant_cpu_to_le16(8); + cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); + ctio->u.status1.response_len = cpu_to_le16(8); ctio->u.status1.sense_data[0] = resp_code; /* Memory Barrier */ @@ -1588,7 +1586,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = prm->cmd->loop_id; - pkt->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; @@ -1903,10 +1901,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, { prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len, (uint32_t)sizeof(ctio->u.status1.sense_data)); - ctio->u.status0.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_SEND_STATUS); + ctio->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_SEND_STATUS); if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) { - ctio->u.status0.flags |= __constant_cpu_to_le16( + ctio->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_EXPLICIT_CONFORM | CTIO7_FLAGS_CONFORM_REQ); } @@ -1923,17 +1920,17 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, "non GOOD status\n"); goto skip_explict_conf; } - ctio->u.status1.flags |= __constant_cpu_to_le16( + ctio->u.status1.flags |= cpu_to_le16( CTIO7_FLAGS_EXPLICIT_CONFORM | CTIO7_FLAGS_CONFORM_REQ); } skip_explict_conf: ctio->u.status1.flags &= - ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); + ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); ctio->u.status1.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); + cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); ctio->u.status1.scsi_status |= - __constant_cpu_to_le16(SS_SENSE_LEN_VALID); + cpu_to_le16(SS_SENSE_LEN_VALID); ctio->u.status1.sense_length = cpu_to_le16(prm->sense_buffer_len); for (i = 0; i < prm->sense_buffer_len/4; i++) @@ -1953,9 +1950,9 @@ skip_explict_conf: #endif } else { ctio->u.status1.flags &= - ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); + ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); ctio->u.status1.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); + cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); ctio->u.status1.sense_length = 0; memset(ctio->u.status1.sense_data, 0, sizeof(ctio->u.status1.sense_data)); @@ -2182,7 +2179,7 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = prm->cmd->loop_id; - pkt->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; @@ -2198,9 +2195,9 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) /* Set transfer direction */ if (cmd->dma_data_direction == DMA_TO_DEVICE) - pkt->flags = __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN); + pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_IN); else if (cmd->dma_data_direction == DMA_FROM_DEVICE) - pkt->flags = __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT); + pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT); pkt->dseg_count = prm->tot_dsds; @@ -2252,11 +2249,11 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) crc_ctx_pkt->blk_size = cpu_to_le16(cmd->blk_sz); crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts); crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); - crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0); + crc_ctx_pkt->guard_seed = cpu_to_le16(0); /* Walks data segments */ - pkt->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DSD_PTR); + pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR); if (!bundling && prm->prot_seg_cnt) { if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd, @@ -2351,7 +2348,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, if (qlt_has_data(cmd) && (xmit_type & QLA_TGT_XMIT_DATA)) { pkt->u.status0.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN | + cpu_to_le16(CTIO7_FLAGS_DATA_IN | CTIO7_FLAGS_STATUS_MODE_0); if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL) @@ -2363,11 +2360,11 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, cpu_to_le16(prm.rq_result); pkt->u.status0.residual = cpu_to_le32(prm.residual); - pkt->u.status0.flags |= __constant_cpu_to_le16( + pkt->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_SEND_STATUS); if (qlt_need_explicit_conf(ha, cmd, 0)) { pkt->u.status0.flags |= - __constant_cpu_to_le16( + cpu_to_le16( CTIO7_FLAGS_EXPLICIT_CONFORM | CTIO7_FLAGS_CONFORM_REQ); } @@ -2395,12 +2392,12 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, ctio->entry_count = 1; ctio->entry_type = CTIO_TYPE7; ctio->dseg_count = 0; - ctio->u.status1.flags &= ~__constant_cpu_to_le16( + ctio->u.status1.flags &= ~cpu_to_le16( CTIO7_FLAGS_DATA_IN); /* Real finish is ctio_m1's finish */ pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK; - pkt->u.status0.flags |= __constant_cpu_to_le16( + pkt->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_DONT_RET_CTIO); /* qlt_24xx_init_ctio_to_isp will correct @@ -2486,7 +2483,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) if (unlikely(res != 0)) goto out_unlock_free_unmap; pkt = (struct ctio7_to_24xx *)prm.pkt; - pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | + pkt->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_DATA_OUT | CTIO7_FLAGS_STATUS_MODE_0); if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL) @@ -2684,14 +2681,14 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, ctio24 = (struct ctio7_to_24xx *)pkt; ctio24->entry_type = CTIO_TYPE7; ctio24->nport_handle = cmd ? cmd->loop_id : CTIO7_NHANDLE_UNRECOGNIZED; - ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio24->vp_index = vha->vp_idx; ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio24->exchange_addr = atio->u.isp24.exchange_addr; ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | + cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio24->u.status1.ox_id = cpu_to_le16(temp); @@ -2912,7 +2909,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, if (ctio != NULL) { struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; term = !(c->flags & - __constant_cpu_to_le16(OF_TERM_EXCH)); + cpu_to_le16(OF_TERM_EXCH)); } else term = 1; @@ -4311,14 +4308,14 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, ctio24 = (struct ctio7_to_24xx *)pkt; ctio24->entry_type = CTIO_TYPE7; ctio24->nport_handle = sess->loop_id; - ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); + ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio24->vp_index = vha->vp_idx; ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio24->exchange_addr = atio->u.isp24.exchange_addr; ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16( + cpu_to_le16( CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS | CTIO7_FLAGS_DONT_RET_CTIO); /* @@ -4646,7 +4643,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) struct atio_from_isp *atio = (struct atio_from_isp *)pkt; int rc; if (atio->u.isp2x.status != - __constant_cpu_to_le16(ATIO_CDB_VALID)) { + cpu_to_le16(ATIO_CDB_VALID)) { ql_dbg(ql_dbg_tgt, vha, 0xe05e, "qla_target(%d): ATIO with error " "status %x received\n", vha->vp_idx, @@ -4720,7 +4717,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) le16_to_cpu(entry->u.isp2x.status)); tgt->notify_ack_expected--; if (entry->u.isp2x.status != - __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) { + cpu_to_le16(NOTIFY_ACK_SUCCESS)) { ql_dbg(ql_dbg_tgt, vha, 0xe061, "qla_target(%d): NOTIFY_ACK " "failed %x\n", vha->vp_idx, @@ -5583,19 +5580,19 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) ha->tgt.saved_set = 1; } - nv->exchange_count = __constant_cpu_to_le16(0xFFFF); + nv->exchange_count = cpu_to_le16(0xFFFF); /* Enable target mode */ - nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4); + nv->firmware_options_1 |= cpu_to_le32(BIT_4); /* Disable ini mode, if requested */ if (!qla_ini_mode_enabled(vha)) - nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_5); + nv->firmware_options_1 |= cpu_to_le32(BIT_5); /* Disable Full Login after LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); + nv->firmware_options_1 &= cpu_to_le32(~BIT_13); /* Enable initial LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9); + nv->firmware_options_1 &= cpu_to_le32(~BIT_9); if (ql2xtgt_tape_enable) /* Enable FC Tape support */ nv->firmware_options_2 |= cpu_to_le32(BIT_12); @@ -5604,9 +5601,9 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) nv->firmware_options_2 &= cpu_to_le32(~BIT_12); /* Disable Full Login after LIP */ - nv->host_p &= __constant_cpu_to_le32(~BIT_10); + nv->host_p &= cpu_to_le32(~BIT_10); /* Enable target PRLI control */ - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14); + nv->firmware_options_2 |= cpu_to_le32(BIT_14); } else { if (ha->tgt.saved_set) { nv->exchange_count = ha->tgt.saved_exchange_count; @@ -5628,12 +5625,12 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) fc_host_supported_classes(vha->host) = FC_COS_CLASS2 | FC_COS_CLASS3; - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8); + nv->firmware_options_2 |= cpu_to_le32(BIT_8); } else { if (vha->flags.init_done) fc_host_supported_classes(vha->host) = FC_COS_CLASS3; - nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8); + nv->firmware_options_2 &= ~cpu_to_le32(BIT_8); } } @@ -5645,7 +5642,7 @@ qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha, if (ha->tgt.node_name_set) { memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE); - icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14); + icb->firmware_options_1 |= cpu_to_le32(BIT_14); } } @@ -5670,20 +5667,19 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) ha->tgt.saved_set = 1; } - nv->exchange_count = __constant_cpu_to_le16(0xFFFF); + nv->exchange_count = cpu_to_le16(0xFFFF); /* Enable target mode */ - nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4); + nv->firmware_options_1 |= cpu_to_le32(BIT_4); /* Disable ini mode, if requested */ if (!qla_ini_mode_enabled(vha)) - nv->firmware_options_1 |= - __constant_cpu_to_le32(BIT_5); + nv->firmware_options_1 |= cpu_to_le32(BIT_5); /* Disable Full Login after LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); + nv->firmware_options_1 &= cpu_to_le32(~BIT_13); /* Enable initial LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9); + nv->firmware_options_1 &= cpu_to_le32(~BIT_9); if (ql2xtgt_tape_enable) /* Enable FC tape support */ nv->firmware_options_2 |= cpu_to_le32(BIT_12); @@ -5692,9 +5688,9 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) nv->firmware_options_2 &= cpu_to_le32(~BIT_12); /* Disable Full Login after LIP */ - nv->host_p &= __constant_cpu_to_le32(~BIT_10); + nv->host_p &= cpu_to_le32(~BIT_10); /* Enable target PRLI control */ - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14); + nv->firmware_options_2 |= cpu_to_le32(BIT_14); } else { if (ha->tgt.saved_set) { nv->exchange_count = ha->tgt.saved_exchange_count; @@ -5716,12 +5712,12 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) fc_host_supported_classes(vha->host) = FC_COS_CLASS2 | FC_COS_CLASS3; - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8); + nv->firmware_options_2 |= cpu_to_le32(BIT_8); } else { if (vha->flags.init_done) fc_host_supported_classes(vha->host) = FC_COS_CLASS3; - nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8); + nv->firmware_options_2 &= ~cpu_to_le32(BIT_8); } } @@ -5736,7 +5732,7 @@ qlt_81xx_config_nvram_stage2(struct scsi_qla_host *vha, if (ha->tgt.node_name_set) { memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE); - icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14); + icb->firmware_options_1 |= cpu_to_le32(BIT_14); } } From 118e2ef9df2297147706d21d2a1dfeefea878c5a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:24:27 -0700 Subject: [PATCH 29/85] qla2xxx: Avoid that sparse complains about duplicate [noderef] attributes Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 3a786e4739ad..1a1a221e1759 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -627,7 +627,7 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) uint32_t cnt, que_idx; uint8_t que_cnt; struct qla2xxx_mq_chain *mq = ptr; - device_reg_t __iomem *reg; + device_reg_t *reg; if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) return ptr; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ceced7ff8083..5a5ca43e5e90 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2085,7 +2085,7 @@ void qla24xx_config_rings(struct scsi_qla_host *vha) { struct qla_hw_data *ha = vha->hw; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, 0); + device_reg_t *reg = ISP_QUE_REG(ha, 0); struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; struct qla_msix_entry *msix; struct init_cb_24xx *icb; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index fbb1fe9fd357..5c0bf290d5df 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -451,7 +451,7 @@ void qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) { struct qla_hw_data *ha = vha->hw; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); + device_reg_t *reg = ISP_QUE_REG(ha, req->id); if (IS_P3P_TYPE(ha)) { qla82xx_start_iocbs(vha); @@ -1795,7 +1795,7 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) { struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); + device_reg_t *reg = ISP_QUE_REG(ha, req->id); uint32_t index, handle; request_t *pkt; uint16_t cnt, req_cnt; From 8dfa4b5a9b44714d7710f9f452f65763629f10df Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:24:50 -0700 Subject: [PATCH 30/85] qla2xxx: Fix sparse annotations This patch removes 21 casts between an __iomem pointer type and another data type but also introduces five new casts (see also the casts with "__force"). Although this patch does not change any functionality, IMHO the code with __force casts needs further review. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 6 +- drivers/scsi/qla2xxx/qla_iocb.c | 12 ++-- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- drivers/scsi/qla2xxx/qla_mr.c | 6 +- drivers/scsi/qla2xxx/qla_nx.c | 107 +++++++++++++++----------------- drivers/scsi/qla2xxx/qla_tmpl.c | 20 +++--- 6 files changed, 71 insertions(+), 82 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e86201d3b8c6..ac88c4e7cf13 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3418,9 +3418,9 @@ struct qla_hw_data { mempool_t *ctx_mempool; #define FCP_CMND_DMA_POOL_SIZE 512 - unsigned long nx_pcibase; /* Base I/O address */ - uint8_t *nxdb_rd_ptr; /* Doorbell read pointer */ - unsigned long nxdb_wr_ptr; /* Door bell write pointer */ + void __iomem *nx_pcibase; /* Base I/O address */ + void __iomem *nxdb_rd_ptr; /* Doorbell read pointer */ + void __iomem *nxdb_wr_ptr; /* Door bell write pointer */ uint32_t crb_win; uint32_t curr_window; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 5c0bf290d5df..e07161c1eda1 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2507,16 +2507,12 @@ sufficient_dsds: /* write, read and verify logic */ dbval = dbval | (req->id << 8) | (req->ring_index << 16); if (ql2xdbwr) - qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); + qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr, dbval); else { - WRT_REG_DWORD( - (unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); + WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); wmb(); - while (RD_REG_DWORD((void __iomem *)ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD( - (unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); + while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { + WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); wmb(); } } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 0c5477f1bfba..26ca18c3fa6a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1239,7 +1239,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) "Entered %s.\n", __func__); if (IS_P3P_TYPE(ha) && ql2xdbwr) - qla82xx_wr_32(ha, ha->nxdb_wr_ptr, + qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr, (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16))); if (ha->flags.npiv_supported) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 2d798e6fadb3..b5029e543b91 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -862,7 +862,7 @@ qlafx00_config_queues(struct scsi_qla_host *vha) dma_addr_t bar2_hdl = pci_resource_start(ha->pdev, 2); req->length = ha->req_que_len; - req->ring = (void *)ha->iobase + ha->req_que_off; + req->ring = (void __force *)ha->iobase + ha->req_que_off; req->dma = bar2_hdl + ha->req_que_off; if ((!req->ring) || (req->length == 0)) { ql_log_pci(ql_log_info, ha->pdev, 0x012f, @@ -877,7 +877,7 @@ qlafx00_config_queues(struct scsi_qla_host *vha) ha->req_que_off, (u64)req->dma); rsp->length = ha->rsp_que_len; - rsp->ring = (void *)ha->iobase + ha->rsp_que_off; + rsp->ring = (void __force *)ha->iobase + ha->rsp_que_off; rsp->dma = bar2_hdl + ha->rsp_que_off; if ((!rsp->ring) || (rsp->length == 0)) { ql_log_pci(ql_log_info, ha->pdev, 0x0131, @@ -1425,7 +1425,7 @@ qlafx00_init_response_q_entries(struct rsp_que *rsp) pkt = rsp->ring_ptr; for (cnt = 0; cnt < rsp->length; cnt++) { pkt->signature = RESPONSE_PROCESSED; - WRT_REG_DWORD((void __iomem *)&pkt->signature, + WRT_REG_DWORD((void __force __iomem *)&pkt->signature, RESPONSE_PROCESSED); pkt++; } diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 264be49d0490..3d3ea84cca07 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -347,32 +347,31 @@ char *qdev_state(uint32_t dev_state) } /* - * In: 'off' is offset from CRB space in 128M pci map - * Out: 'off' is 2M pci map addr + * In: 'off_in' is offset from CRB space in 128M pci map + * Out: 'off_out' is 2M pci map addr * side effect: lock crb window */ static void -qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off) +qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong off_in, + void __iomem **off_out) { u32 win_read; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); - ha->crb_win = CRB_HI(*off); - writel(ha->crb_win, - (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); + ha->crb_win = CRB_HI(off_in); + writel(ha->crb_win, CRB_WINDOW_2M + ha->nx_pcibase); /* Read back value to make sure write has gone through before trying * to use it. */ - win_read = RD_REG_DWORD((void __iomem *) - (CRB_WINDOW_2M + ha->nx_pcibase)); + win_read = RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase); if (win_read != ha->crb_win) { ql_dbg(ql_dbg_p3p, vha, 0xb000, "%s: Written crbwin (0x%x) " "!= Read crbwin (0x%x), off=0x%lx.\n", - __func__, ha->crb_win, win_read, *off); + __func__, ha->crb_win, win_read, off_in); } - *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; + *off_out = (off_in & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; } static inline unsigned long @@ -417,29 +416,30 @@ qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off) } static int -qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off) +qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong off_in, + void __iomem **off_out) { struct crb_128M_2M_sub_block_map *m; - if (*off >= QLA82XX_CRB_MAX) + if (off_in >= QLA82XX_CRB_MAX) return -1; - if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { - *off = (*off - QLA82XX_PCI_CAMQM) + + if (off_in >= QLA82XX_PCI_CAMQM && off_in < QLA82XX_PCI_CAMQM_2M_END) { + *off_out = (off_in - QLA82XX_PCI_CAMQM) + QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; return 0; } - if (*off < QLA82XX_PCI_CRBSPACE) + if (off_in < QLA82XX_PCI_CRBSPACE) return -1; - *off -= QLA82XX_PCI_CRBSPACE; + *off_out = (void __iomem *)(off_in - QLA82XX_PCI_CRBSPACE); /* Try direct map */ - m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; + m = &crb_128M_2M_map[CRB_BLK(off_in)].sub_block[CRB_SUBBLK(off_in)]; - if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { - *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; + if (m->valid && (m->start_128M <= off_in) && (m->end_128M > off_in)) { + *off_out = off_in + m->start_2M - m->start_128M + ha->nx_pcibase; return 0; } /* Not in direct map, use crb window */ @@ -465,19 +465,20 @@ static int qla82xx_crb_win_lock(struct qla_hw_data *ha) } int -qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data) +qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data) { + void __iomem *off; unsigned long flags = 0; int rv; - rv = qla82xx_pci_get_crb_addr_2M(ha, &off); + rv = qla82xx_pci_get_crb_addr_2M(ha, off_in, &off); BUG_ON(rv == -1); if (rv == 1) { write_lock_irqsave(&ha->hw_lock, flags); qla82xx_crb_win_lock(ha); - qla82xx_pci_set_crbwindow_2M(ha, &off); + qla82xx_pci_set_crbwindow_2M(ha, off_in, &off); } writel(data, (void __iomem *)off); @@ -490,22 +491,23 @@ qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data) } int -qla82xx_rd_32(struct qla_hw_data *ha, ulong off) +qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in) { + void __iomem *off; unsigned long flags = 0; int rv; u32 data; - rv = qla82xx_pci_get_crb_addr_2M(ha, &off); + rv = qla82xx_pci_get_crb_addr_2M(ha, off_in, &off); BUG_ON(rv == -1); if (rv == 1) { write_lock_irqsave(&ha->hw_lock, flags); qla82xx_crb_win_lock(ha); - qla82xx_pci_set_crbwindow_2M(ha, &off); + qla82xx_pci_set_crbwindow_2M(ha, off_in, &off); } - data = RD_REG_DWORD((void __iomem *)off); + data = RD_REG_DWORD(off); if (rv == 1) { qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); @@ -919,20 +921,18 @@ qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag) { uint32_t off_value, rval = 0; - WRT_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase), - (off & 0xFFFF0000)); + WRT_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase, off & 0xFFFF0000); /* Read back value to make sure write has gone through */ - RD_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); + RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase); off_value = (off & 0x0000FFFF); if (flag) - WRT_REG_DWORD((void __iomem *) - (off_value + CRB_INDIRECT_2M + ha->nx_pcibase), - data); + WRT_REG_DWORD(off_value + CRB_INDIRECT_2M + ha->nx_pcibase, + data); else - rval = RD_REG_DWORD((void __iomem *) - (off_value + CRB_INDIRECT_2M + ha->nx_pcibase)); + rval = RD_REG_DWORD(off_value + CRB_INDIRECT_2M + + ha->nx_pcibase); return rval; } @@ -1660,8 +1660,7 @@ qla82xx_iospace_config(struct qla_hw_data *ha) } len = pci_resource_len(ha->pdev, 0); - ha->nx_pcibase = - (unsigned long)ioremap(pci_resource_start(ha->pdev, 0), len); + ha->nx_pcibase = ioremap(pci_resource_start(ha->pdev, 0), len); if (!ha->nx_pcibase) { ql_log_pci(ql_log_fatal, ha->pdev, 0x000e, "Cannot remap pcibase MMIO, aborting.\n"); @@ -1670,17 +1669,13 @@ qla82xx_iospace_config(struct qla_hw_data *ha) /* Mapping of IO base pointer */ if (IS_QLA8044(ha)) { - ha->iobase = - (device_reg_t *)((uint8_t *)ha->nx_pcibase); + ha->iobase = ha->nx_pcibase; } else if (IS_QLA82XX(ha)) { - ha->iobase = - (device_reg_t *)((uint8_t *)ha->nx_pcibase + - 0xbc000 + (ha->pdev->devfn << 11)); + ha->iobase = ha->nx_pcibase + 0xbc000 + (ha->pdev->devfn << 11); } if (!ql2xdbwr) { - ha->nxdb_wr_ptr = - (unsigned long)ioremap((pci_resource_start(ha->pdev, 4) + + ha->nxdb_wr_ptr = ioremap((pci_resource_start(ha->pdev, 4) + (ha->pdev->devfn << 12)), 4); if (!ha->nxdb_wr_ptr) { ql_log_pci(ql_log_fatal, ha->pdev, 0x000f, @@ -1691,10 +1686,10 @@ qla82xx_iospace_config(struct qla_hw_data *ha) /* Mapping of IO base pointer, * door bell read and write pointer */ - ha->nxdb_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + + ha->nxdb_rd_ptr = ha->nx_pcibase + (512 * 1024) + (ha->pdev->devfn * 8); } else { - ha->nxdb_wr_ptr = (ha->pdev->devfn == 6 ? + ha->nxdb_wr_ptr = (void __iomem *)(ha->pdev->devfn == 6 ? QLA82XX_CAMRAM_DB1 : QLA82XX_CAMRAM_DB2); } @@ -1704,12 +1699,12 @@ qla82xx_iospace_config(struct qla_hw_data *ha) ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc006, "nx_pci_base=%p iobase=%p " "max_req_queues=%d msix_count=%d.\n", - (void *)ha->nx_pcibase, ha->iobase, + ha->nx_pcibase, ha->iobase, ha->max_req_queues, ha->msix_count); ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0010, "nx_pci_base=%p iobase=%p " "max_req_queues=%d msix_count=%d.\n", - (void *)ha->nx_pcibase, ha->iobase, + ha->nx_pcibase, ha->iobase, ha->max_req_queues, ha->msix_count); return 0; @@ -1774,9 +1769,9 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); - WRT_REG_DWORD((unsigned long __iomem *)®->req_q_out[0], 0); - WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_in[0], 0); - WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); + WRT_REG_DWORD(®->req_q_out[0], 0); + WRT_REG_DWORD(®->rsp_q_in[0], 0); + WRT_REG_DWORD(®->rsp_q_out[0], 0); } static int @@ -2799,13 +2794,12 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha) dbval = dbval | (req->id << 8) | (req->ring_index << 16); if (ql2xdbwr) - qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); + qla82xx_wr_32(ha, (unsigned long)ha->nxdb_wr_ptr, dbval); else { - WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); + WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); wmb(); - while (RD_REG_DWORD((void __iomem *)ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); + while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { + WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); wmb(); } } @@ -3836,8 +3830,7 @@ qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha, loop_cnt = ocm_hdr->op_count; for (i = 0; i < loop_cnt; i++) { - r_value = RD_REG_DWORD((void __iomem *) - (r_addr + ha->nx_pcibase)); + r_value = RD_REG_DWORD(r_addr + ha->nx_pcibase); *data_ptr++ = cpu_to_le32(r_value); r_addr += r_stride; } diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 7e876d1e2f78..f4eb65524ae4 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -137,39 +137,39 @@ qla27xx_insertbuf(void *mem, ulong size, void *buf, ulong *len) } static inline void -qla27xx_read8(void *window, void *buf, ulong *len) +qla27xx_read8(void __iomem *window, void *buf, ulong *len) { uint8_t value = ~0; if (buf) { - value = RD_REG_BYTE((__iomem void *)window); + value = RD_REG_BYTE(window); } qla27xx_insert32(value, buf, len); } static inline void -qla27xx_read16(void *window, void *buf, ulong *len) +qla27xx_read16(void __iomem *window, void *buf, ulong *len) { uint16_t value = ~0; if (buf) { - value = RD_REG_WORD((__iomem void *)window); + value = RD_REG_WORD(window); } qla27xx_insert32(value, buf, len); } static inline void -qla27xx_read32(void *window, void *buf, ulong *len) +qla27xx_read32(void __iomem *window, void *buf, ulong *len) { uint32_t value = ~0; if (buf) { - value = RD_REG_DWORD((__iomem void *)window); + value = RD_REG_DWORD(window); } qla27xx_insert32(value, buf, len); } -static inline void (*qla27xx_read_vector(uint width))(void *, void *, ulong *) +static inline void (*qla27xx_read_vector(uint width))(void __iomem*, void *, ulong *) { return (width == 1) ? qla27xx_read8 : @@ -181,7 +181,7 @@ static inline void qla27xx_read_reg(__iomem struct device_reg_24xx *reg, uint offset, void *buf, ulong *len) { - void *window = (void *)reg + offset; + void __iomem *window = (void __iomem *)reg + offset; qla27xx_read32(window, buf, len); } @@ -202,8 +202,8 @@ qla27xx_read_window(__iomem struct device_reg_24xx *reg, uint32_t addr, uint offset, uint count, uint width, void *buf, ulong *len) { - void *window = (void *)reg + offset; - void (*readn)(void *, void *, ulong *) = qla27xx_read_vector(width); + void __iomem *window = (void __iomem *)reg + offset; + void (*readn)(void __iomem*, void *, ulong *) = qla27xx_read_vector(width); qla27xx_write_reg(reg, IOBASE_ADDR, addr, buf); while (count--) { From 82e6afd49d9a5da8cdb648cb66e54432173298d7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:25:07 -0700 Subject: [PATCH 31/85] qla2xxx: Remove a superfluous test Avoid that smatch reports the following warning: drivers/scsi/qla2xxx/qla_attr.c:1081: qla2x00_model_desc_show() warn: this array is probably non-NULL. 'vha->hw->model_desc' Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 741d6e0f4060..2087b73927ce 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1077,8 +1077,7 @@ qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); - return scnprintf(buf, PAGE_SIZE, "%s\n", - vha->hw->model_desc ? vha->hw->model_desc : ""); + return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_desc); } static ssize_t From 8a318fe16096a45c03e8c9a39449d1f750fafd27 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:25:25 -0700 Subject: [PATCH 32/85] qla2xxx: Remove dead code The "return QLA_SUCCESS" statement just above the "fw_load_failed" label cannot be reached, hence remove it. Additionally remove the "else" keyword since the code block below the if-statement ends with a return statement. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 3d3ea84cca07..bb0ee7c604c7 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2473,14 +2473,12 @@ try_blob_fw: ql_log(ql_log_info, vha, 0x00a5, "Firmware loaded successfully from binary blob.\n"); return QLA_SUCCESS; - } else { - ql_log(ql_log_fatal, vha, 0x00a6, - "Firmware load failed for binary blob.\n"); - blob->fw = NULL; - blob = NULL; - goto fw_load_failed; } - return QLA_SUCCESS; + + ql_log(ql_log_fatal, vha, 0x00a6, + "Firmware load failed for binary blob.\n"); + blob->fw = NULL; + blob = NULL; fw_load_failed: return QLA_FUNCTION_FAILED; From 8d16366b5f23e928e5fd22eaeaceeb0356921fc0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 9 Jul 2015 07:25:46 -0700 Subject: [PATCH 33/85] qla2xxx: Avoid that sparse complains about context imbalances Surround conditional locking statements with "#ifndef __CHECKER__" / "#endif" to hide these for the sparse static source code analysis tool. Signed-off-by: Bart Van Assche Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 36 +++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_nx.c | 8 +++++++ drivers/scsi/qla2xxx/qla_target.c | 4 ++++ drivers/scsi/qla2xxx/qla_tmpl.c | 4 ++++ 4 files changed, 52 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 1a1a221e1759..583d52aae79d 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -695,8 +695,10 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd002, @@ -832,8 +834,12 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) qla2xxx_dump_post_process(base_vha, rval); qla2300_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } /** @@ -859,8 +865,10 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) mb0 = mb2 = 0; flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd004, @@ -1030,8 +1038,12 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) qla2xxx_dump_post_process(base_vha, rval); qla2100_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } void @@ -1057,8 +1069,10 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) flags = 0; ha->fw_dump_cap_flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd006, @@ -1282,8 +1296,12 @@ qla24xx_fw_dump_failed_0: qla2xxx_dump_post_process(base_vha, rval); qla24xx_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } void @@ -1305,8 +1323,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) flags = 0; ha->fw_dump_cap_flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd008, @@ -1598,8 +1618,12 @@ qla25xx_fw_dump_failed_0: qla2xxx_dump_post_process(base_vha, rval); qla25xx_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } void @@ -1621,8 +1645,10 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) flags = 0; ha->fw_dump_cap_flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd00a, @@ -1916,8 +1942,12 @@ qla81xx_fw_dump_failed_0: qla2xxx_dump_post_process(base_vha, rval); qla81xx_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } void @@ -1939,8 +1969,10 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) flags = 0; ha->fw_dump_cap_flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif if (!ha->fw_dump) { ql_log(ql_log_warn, vha, 0xd00c, @@ -2419,8 +2451,12 @@ qla83xx_fw_dump_failed_0: qla2xxx_dump_post_process(base_vha, rval); qla83xx_fw_dump_failed: +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#else + ; +#endif } /****************************************************************************/ diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index bb0ee7c604c7..eb0cc5475c45 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -476,7 +476,9 @@ qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data) BUG_ON(rv == -1); if (rv == 1) { +#ifndef __CHECKER__ write_lock_irqsave(&ha->hw_lock, flags); +#endif qla82xx_crb_win_lock(ha); qla82xx_pci_set_crbwindow_2M(ha, off_in, &off); } @@ -485,7 +487,9 @@ qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data) if (rv == 1) { qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); +#ifndef __CHECKER__ write_unlock_irqrestore(&ha->hw_lock, flags); +#endif } return 0; } @@ -503,7 +507,9 @@ qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in) BUG_ON(rv == -1); if (rv == 1) { +#ifndef __CHECKER__ write_lock_irqsave(&ha->hw_lock, flags); +#endif qla82xx_crb_win_lock(ha); qla82xx_pci_set_crbwindow_2M(ha, off_in, &off); } @@ -511,7 +517,9 @@ qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in) if (rv == 1) { qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); +#ifndef __CHECKER__ write_unlock_irqrestore(&ha->hw_lock, flags); +#endif } return data; } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 445af44c9a7a..6b7736d02534 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3955,16 +3955,20 @@ static void qlt_reject_free_srr_imm(struct scsi_qla_host *vha, struct qla_hw_data *ha = vha->hw; unsigned long flags = 0; +#ifndef __CHECKER__ if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); +#endif qlt_send_notify_ack(vha, (void *)&imm->imm_ntfy, 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT, NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); +#ifndef __CHECKER__ if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif kfree(imm); } diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index f4eb65524ae4..ddbe2e7ac14d 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -939,8 +939,10 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) { ulong flags = 0; +#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&vha->hw->hardware_lock, flags); +#endif if (!vha->hw->fw_dump) ql_log(ql_log_warn, vha, 0xd01e, "fwdump buffer missing.\n"); @@ -953,6 +955,8 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) else qla27xx_execute_fwdt_template(vha); +#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); +#endif } From 5aeeb78aeb4c8607cbda54a7b0dc7315171e214f Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Wed, 15 Jul 2015 10:19:56 +0530 Subject: [PATCH 34/85] mpt2sas, mpt3sas: Abort initialization if no memory I/O resources detected Driver crashes if the BIOS do not set up at least one memory I/O resource. This failure can happen if the device is too slow to respond during POST and is missed by the BIOS, but Linux then detects the device later in the boot process. Based on a patch from Timothy Pearson Signed-off-by: Sreekanth Reddy Reviewed-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 16 +++++++++------- drivers/scsi/mpt3sas/mpt3sas_base.c | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 11248de92b3b..6dec7cff316f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1557,7 +1557,8 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) goto out_fail; } - for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { + for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) && + (!memap_sz || !pio_sz); i++) { if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { if (pio_sz) continue; @@ -1572,16 +1573,17 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) chip_phys = (u64)ioc->chip_phys; memap_sz = pci_resource_len(pdev, i); ioc->chip = ioremap(ioc->chip_phys, memap_sz); - if (ioc->chip == NULL) { - printk(MPT2SAS_ERR_FMT "unable to map " - "adapter memory!\n", ioc->name); - r = -EINVAL; - goto out_fail; - } } } } + if (ioc->chip == NULL) { + printk(MPT2SAS_ERR_FMT "unable to map adapter memory! " + "or resource not found\n", ioc->name); + r = -EINVAL; + goto out_fail; + } + _base_mask_interrupts(ioc); r = _base_get_ioc_facts(ioc, CAN_SLEEP); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 14a781b6b88d..43f87e904b98 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1843,7 +1843,8 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) goto out_fail; } - for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { + for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) && + (!memap_sz || !pio_sz); i++) { if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { if (pio_sz) continue; @@ -1856,15 +1857,16 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) chip_phys = (u64)ioc->chip_phys; memap_sz = pci_resource_len(pdev, i); ioc->chip = ioremap(ioc->chip_phys, memap_sz); - if (ioc->chip == NULL) { - pr_err(MPT3SAS_FMT "unable to map adapter memory!\n", - ioc->name); - r = -EINVAL; - goto out_fail; - } } } + if (ioc->chip == NULL) { + pr_err(MPT3SAS_FMT "unable to map adapter memory! " + " or resource not found\n", ioc->name); + r = -EINVAL; + goto out_fail; + } + _base_mask_interrupts(ioc); r = _base_get_ioc_facts(ioc, CAN_SLEEP); From 77678d3a35455d7b7c4da4e56b20de17ee63cec1 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:22 -0500 Subject: [PATCH 35/85] hpsa: Correct double unlock of mutex Reported-by: Dan Carpenter Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index cab4e98b2b0e..cb11421f9cb8 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2749,11 +2749,10 @@ static int hpsa_do_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, lockup_detected(h)); if (unlikely(lockup_detected(h))) { - dev_warn(&h->pdev->dev, - "Controller lockup detected during reset wait\n"); - mutex_unlock(&h->reset_mutex); - rc = -ENODEV; - } + dev_warn(&h->pdev->dev, + "Controller lockup detected during reset wait\n"); + rc = -ENODEV; + } if (unlikely(rc)) atomic_set(&dev->reset_cmds_out, 0); From 81c275576bcee1a80e046117c7923586216a2dd4 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:28 -0500 Subject: [PATCH 36/85] hpsa: correct decode sense data Reported-by: Dan Carpenter Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index cb11421f9cb8..ce9122d37a8b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -325,7 +325,7 @@ static int check_for_unit_attention(struct ctlr_info *h, decode_sense_data(c->err_info->SenseInfo, sense_len, &sense_key, &asc, &ascq); - if (sense_key != UNIT_ATTENTION || asc == -1) + if (sense_key != UNIT_ATTENTION || asc == 0xff) return 0; switch (asc) { From 7ef7323f4bf467ce9fe51177301ad8cbb7dc2631 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:33 -0500 Subject: [PATCH 37/85] hpsa: correct static checker warnings on driver init cleanup Reported-by: Dan Carpenter Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ce9122d37a8b..47d02871371d 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8056,7 +8056,7 @@ reinit_after_soft_reset: rc = hpsa_kdump_soft_reset(h); if (rc) /* Neither hard nor soft reset worked, we're hosed. */ - goto clean9; + goto clean7; dev_info(&h->pdev->dev, "Board READY.\n"); dev_info(&h->pdev->dev, @@ -8102,8 +8102,6 @@ reinit_after_soft_reset: h->heartbeat_sample_interval); return 0; -clean9: /* wq, sh, perf, sg, cmd, irq, shost, pci, lu, aer/h */ - kfree(h->hba_inquiry_data); clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ hpsa_free_performant_mode(h); h->access.set_intr_mask(h, HPSA_INTR_OFF); From 1358f6dc5875f5cef06eeeeb4532f382aaff8483 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:38 -0500 Subject: [PATCH 38/85] hpsa: add PMC to copyright need to add PMC to copyright notice and update the Hewlett-Packard copyright notification. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Justin Lindley Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 9 +++------ drivers/scsi/hpsa.h | 9 +++------ drivers/scsi/hpsa_cmd.h | 9 +++------ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 47d02871371d..984bbd9e0535 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1,6 +1,7 @@ /* * Disk Array driver for HP Smart Array SAS controllers - * Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + * Copyright 2014-2015 PMC-Sierra, Inc. + * Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,11 +12,7 @@ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to iss_storagedev@hp.com + * Questions/Comments/Bugfixes to storagedev@pmcs.com * */ diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 6ee4da6b1153..6f6084b39420 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -1,6 +1,7 @@ /* * Disk Array driver for HP Smart Array SAS controllers - * Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + * Copyright 2014-2015 PMC-Sierra, Inc. + * Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,11 +12,7 @@ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to iss_storagedev@hp.com + * Questions/Comments/Bugfixes to storagedev@pmcs.com * */ #ifndef HPSA_H diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index c601622cc98e..1a98bbebf15b 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -1,6 +1,7 @@ /* * Disk Array driver for HP Smart Array SAS controllers - * Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + * Copyright 2014-2015 PMC-Sierra, Inc. + * Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,11 +12,7 @@ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Questions/Comments/Bugfixes to iss_storagedev@hp.com + * Questions/Comments/Bugfixes to storagedev@pmcs.com * */ #ifndef HPSA_CMD_H From 8270b8624365887a716615294d0ac28af07c9287 Mon Sep 17 00:00:00 2001 From: Joe Handzik Date: Sat, 18 Jul 2015 11:12:43 -0500 Subject: [PATCH 39/85] hpsa: add sysfs entry path_info to show box and bay information host no, bus, target, lun, scsi_device_type for hba mode add: box and bay information report if the path is active/inactive Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/hpsa.h | 5 ++ 2 files changed, 127 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 984bbd9e0535..43c34a61c66c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -264,6 +264,7 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, static void hpsa_command_resubmit_worker(struct work_struct *work); static u32 lockup_detected(struct ctlr_info *h); static int detect_controller_lockup(struct ctlr_info *h); +static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { @@ -714,12 +715,106 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, return snprintf(buf, 20, "%d\n", offload_enabled); } +#define MAX_PATHS 8 +#define PATH_STRING_LEN 50 + +static ssize_t path_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctlr_info *h; + struct scsi_device *sdev; + struct hpsa_scsi_dev_t *hdev; + unsigned long flags; + int i; + int output_len = 0; + u8 box; + u8 bay; + u8 path_map_index = 0; + char *active; + unsigned char phys_connector[2]; + unsigned char path[MAX_PATHS][PATH_STRING_LEN]; + + memset(path, 0, MAX_PATHS * PATH_STRING_LEN); + sdev = to_scsi_device(dev); + h = sdev_to_hba(sdev); + spin_lock_irqsave(&h->devlock, flags); + hdev = sdev->hostdata; + if (!hdev) { + spin_unlock_irqrestore(&h->devlock, flags); + return -ENODEV; + } + + bay = hdev->bay; + for (i = 0; i < MAX_PATHS; i++) { + path_map_index = 1<active_path_index) + active = "Active"; + else if (hdev->path_map & path_map_index) + active = "Inactive"; + else + continue; + + output_len = snprintf(path[i], + PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ", + h->scsi_host->host_no, + hdev->bus, hdev->target, hdev->lun, + scsi_device_type(hdev->devtype)); + + if (is_ext_target(h, hdev) || + (hdev->devtype == TYPE_RAID) || + is_logical_dev_addr_mode(hdev->scsi3addr)) { + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, "%s\n", + active); + continue; + } + + box = hdev->box[i]; + memcpy(&phys_connector, &hdev->phys_connector[i], + sizeof(phys_connector)); + if (phys_connector[0] < '0') + phys_connector[0] = '0'; + if (phys_connector[1] < '0') + phys_connector[1] = '0'; + if (hdev->phys_connector[i] > 0) + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, + "PORT: %.2s ", + phys_connector); + if (hdev->devtype == TYPE_DISK && h->hba_mode_enabled) { + if (box == 0 || box == 0xFF) { + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, + "BAY: %hhu %s\n", + bay, active); + } else { + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, + "BOX: %hhu BAY: %hhu %s\n", + box, bay, active); + } + } else if (box != 0 && box != 0xFF) { + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, "BOX: %hhu %s\n", + box, active); + } else + output_len += snprintf(path[i] + output_len, + PATH_STRING_LEN, "%s\n", active); + } + + spin_unlock_irqrestore(&h->devlock, flags); + return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s", + path[0], path[1], path[2], path[3], + path[4], path[5], path[6], path[7]); +} + static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO, host_show_hp_ssd_smart_path_enabled, NULL); +static DEVICE_ATTR(path_info, S_IRUGO, path_info_show, NULL); static DEVICE_ATTR(hp_ssd_smart_path_status, S_IWUSR|S_IRUGO|S_IROTH, host_show_hp_ssd_smart_path_status, host_store_hp_ssd_smart_path_status); @@ -741,6 +836,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_lunid, &dev_attr_unique_id, &dev_attr_hp_ssd_smart_path_enabled, + &dev_attr_path_info, &dev_attr_lockup_detected, NULL, }; @@ -3611,6 +3707,31 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, atomic_set(&dev->reset_cmds_out, 0); } +static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, + u8 *lunaddrbytes, + struct bmic_identify_physical_device *id_phys) +{ + if (PHYS_IOACCEL(lunaddrbytes) + && this_device->ioaccel_handle) + this_device->hba_ioaccel_enabled = 1; + + memcpy(&this_device->active_path_index, + &id_phys->active_path_number, + sizeof(this_device->active_path_index)); + memcpy(&this_device->path_map, + &id_phys->redundant_path_present_map, + sizeof(this_device->path_map)); + memcpy(&this_device->box, + &id_phys->alternate_paths_phys_box_on_port, + sizeof(this_device->box)); + memcpy(&this_device->phys_connector, + &id_phys->alternate_paths_phys_connector, + sizeof(this_device->phys_connector)); + memcpy(&this_device->bay, + &id_phys->phys_bay_in_box, + sizeof(this_device->bay)); +} + static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) { /* the idea here is we could get notified @@ -3771,6 +3892,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) hpsa_get_ioaccel_drive_info(h, this_device, lunaddrbytes, id_phys); + hpsa_get_path_info(this_device, lunaddrbytes, id_phys); atomic_set(&this_device->ioaccel_cmds_out, 0); ncurrent++; break; diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 6f6084b39420..ab014d3f3656 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -50,6 +50,11 @@ struct hpsa_scsi_dev_t { * device via "ioaccel" path. */ u32 ioaccel_handle; + u8 active_path_index; + u8 path_map; + u8 bay; + u8 box[8]; + u16 phys_connector[8]; int offload_config; /* I/O accel RAID offload configured */ int offload_enabled; /* I/O accel RAID offload enabled */ int offload_to_be_enabled; From 9384950809d96ee08dcd7bb2eadc9628b99d0474 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:49 -0500 Subject: [PATCH 40/85] hpsa: cleanup update scsi devices showing that tables have been updated unnecessarily. Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 43c34a61c66c..9d3291379b29 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1379,8 +1379,9 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, return 1; if (dev1->offload_enabled != dev2->offload_enabled) return 1; - if (dev1->queue_depth != dev2->queue_depth) - return 1; + if (!is_logical_dev_addr_mode(dev1->scsi3addr)) + if (dev1->queue_depth != dev2->queue_depth) + return 1; return 0; } @@ -3889,7 +3890,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) else if (!(h->transMethod & CFGTBL_Trans_io_accel1 || h->transMethod & CFGTBL_Trans_io_accel2)) break; - hpsa_get_ioaccel_drive_info(h, this_device, lunaddrbytes, id_phys); hpsa_get_path_info(this_device, lunaddrbytes, id_phys); From cbb47dcbb405d4a694801e6ad6d63c2992f83bb4 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:12:54 -0500 Subject: [PATCH 41/85] hpsa: add in new controllers Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Signed-off-by: Don Brace Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9d3291379b29..212e82663707 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -129,6 +129,11 @@ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CD}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CE}, {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0580}, + {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0581}, + {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0582}, + {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0583}, + {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0584}, + {PCI_VENDOR_ID_ADAPTEC2, 0x0290, 0x9005, 0x0585}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0076}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0087}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x007D}, @@ -187,6 +192,11 @@ static struct board_type products[] = { {0x21CD103C, "Smart Array", &SA5_access}, {0x21CE103C, "Smart HBA", &SA5_access}, {0x05809005, "SmartHBA-SA", &SA5_access}, + {0x05819005, "SmartHBA-SA 8i", &SA5_access}, + {0x05829005, "SmartHBA-SA 8i8e", &SA5_access}, + {0x05839005, "SmartHBA-SA 8e", &SA5_access}, + {0x05849005, "SmartHBA-SA 16i", &SA5_access}, + {0x05859005, "SmartHBA-SA 4i4e", &SA5_access}, {0x00761590, "HP Storage P1224 Array Controller", &SA5_access}, {0x00871590, "HP Storage P1224e Array Controller", &SA5_access}, {0x007D1590, "HP Storage P1228 Array Controller", &SA5_access}, From b9092b79ccaf4404509d6aeb2c76eb7cbfa57bf1 Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Sat, 18 Jul 2015 11:12:59 -0500 Subject: [PATCH 42/85] Change how controllers in mixed mode are handled. Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 97 +++++---------------------------------------- drivers/scsi/hpsa.h | 2 - 2 files changed, 11 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 212e82663707..bf877eb61016 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -791,7 +791,8 @@ static ssize_t path_info_show(struct device *dev, PATH_STRING_LEN, "PORT: %.2s ", phys_connector); - if (hdev->devtype == TYPE_DISK && h->hba_mode_enabled) { + if (hdev->devtype == TYPE_DISK && + hdev->expose_state != HPSA_DO_NOT_EXPOSE) { if (box == 0 || box == 0xFF) { output_len += snprintf(path[i] + output_len, PATH_STRING_LEN, @@ -2689,34 +2690,6 @@ out: return rc; } -static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, - unsigned char *scsi3addr, unsigned char page, - struct bmic_controller_parameters *buf, size_t bufsize) -{ - int rc = IO_OK; - struct CommandList *c; - struct ErrorInfo *ei; - - c = cmd_alloc(h); - if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, bufsize, - page, scsi3addr, TYPE_CMD)) { - rc = -1; - goto out; - } - rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); - if (rc) - goto out; - ei = c->err_info; - if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { - hpsa_scsi_interpret_error(h, c); - rc = -1; - } -out: - cmd_free(h, c); - return rc; -} - static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, u8 reset_type, int reply_queue) { @@ -3665,29 +3638,6 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, return NULL; } -static int hpsa_hba_mode_enabled(struct ctlr_info *h) -{ - int rc; - int hba_mode_enabled; - struct bmic_controller_parameters *ctlr_params; - ctlr_params = kzalloc(sizeof(struct bmic_controller_parameters), - GFP_KERNEL); - - if (!ctlr_params) - return -ENOMEM; - rc = hpsa_bmic_ctrl_mode_sense(h, RAID_CTLR_LUNID, 0, ctlr_params, - sizeof(struct bmic_controller_parameters)); - if (rc) { - kfree(ctlr_params); - return rc; - } - - hba_mode_enabled = - ((ctlr_params->nvram_flags & HBA_MODE_ENABLED_FLAG) != 0); - kfree(ctlr_params); - return hba_mode_enabled; -} - /* get physical drive ioaccel handle and queue depth */ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, @@ -3765,7 +3715,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) int ncurrent = 0; int i, n_ext_target_devs, ndevs_to_allocate; int raid_ctlr_position; - int rescan_hba_mode; DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL); @@ -3781,17 +3730,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) } memset(lunzerobits, 0, sizeof(lunzerobits)); - rescan_hba_mode = hpsa_hba_mode_enabled(h); - if (rescan_hba_mode < 0) - goto out; - - if (!h->hba_mode_enabled && rescan_hba_mode) - dev_warn(&h->pdev->dev, "HBA mode enabled\n"); - else if (h->hba_mode_enabled && !rescan_hba_mode) - dev_warn(&h->pdev->dev, "HBA mode disabled\n"); - - h->hba_mode_enabled = rescan_hba_mode; - if (hpsa_gather_lun_info(h, physdev_list, &nphysicals, logdev_list, &nlogicals)) goto out; @@ -3867,9 +3805,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) /* do not expose masked devices */ if (MASKED_DEVICE(lunaddrbytes) && i < nphysicals + (raid_ctlr_position == 0)) { - if (h->hba_mode_enabled) - dev_warn(&h->pdev->dev, - "Masked physical device detected\n"); this_device->expose_state = HPSA_DO_NOT_EXPOSE; } else { this_device->expose_state = @@ -3889,30 +3824,21 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ncurrent++; break; case TYPE_DISK: - if (i >= nphysicals) { - ncurrent++; - break; - } - - if (h->hba_mode_enabled) - /* never use raid mapper in HBA mode */ + if (i < nphysicals + (raid_ctlr_position == 0)) { + /* The disk is in HBA mode. */ + /* Never use RAID mapper in HBA mode. */ this_device->offload_enabled = 0; - else if (!(h->transMethod & CFGTBL_Trans_io_accel1 || - h->transMethod & CFGTBL_Trans_io_accel2)) - break; - hpsa_get_ioaccel_drive_info(h, this_device, - lunaddrbytes, id_phys); - hpsa_get_path_info(this_device, lunaddrbytes, id_phys); - atomic_set(&this_device->ioaccel_cmds_out, 0); + hpsa_get_ioaccel_drive_info(h, this_device, + lunaddrbytes, id_phys); + hpsa_get_path_info(this_device, lunaddrbytes, + id_phys); + } ncurrent++; break; case TYPE_TAPE: case TYPE_MEDIUM_CHANGER: - ncurrent++; - break; case TYPE_ENCLOSURE: - if (h->hba_mode_enabled) - ncurrent++; + ncurrent++; break; case TYPE_RAID: /* Only present the Smartarray HBA as a RAID controller. @@ -8120,7 +8046,6 @@ reinit_after_soft_reset: pci_set_drvdata(pdev, h); h->ndevices = 0; - h->hba_mode_enabled = 0; spin_lock_init(&h->devlock); rc = hpsa_put_ctlr_into_performant_mode(h); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index ab014d3f3656..27debb363529 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -116,7 +116,6 @@ struct bmic_controller_parameters { u8 automatic_drive_slamming; u8 reserved1; u8 nvram_flags; -#define HBA_MODE_ENABLED_FLAG (1 << 3) u8 cache_nvram_flags; u8 drive_config_flags; u16 reserved2; @@ -155,7 +154,6 @@ struct ctlr_info { unsigned int msi_vector; int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ struct access_method access; - char hba_mode_enabled; /* queue and queue Info */ unsigned int Qdepth; From 5ca0120447ae8d485e2ee5100f25b6645e3e320f Mon Sep 17 00:00:00 2001 From: Scott Benesh Date: Sat, 18 Jul 2015 11:13:04 -0500 Subject: [PATCH 43/85] hpsa: add in new offline mode prevent adding volumes that are not available. Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 15 +++++++++++---- drivers/scsi/hpsa_cmd.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index bf877eb61016..07512463b990 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1481,17 +1481,23 @@ static void hpsa_show_volume_status(struct ctlr_info *h, h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; + case HPSA_LV_NOT_AVAILABLE: + dev_info(&h->pdev->dev, + "C%d:B%d:T%d:L%d Volume is waiting for transforming volume.\n", + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); + break; case HPSA_LV_UNDERGOING_RPI: dev_info(&h->pdev->dev, - "C%d:B%d:T%d:L%d Volume is undergoing rapid parity initialization process.\n", + "C%d:B%d:T%d:L%d Volume is undergoing rapid parity init.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_PENDING_RPI: dev_info(&h->pdev->dev, - "C%d:B%d:T%d:L%d Volume is queued for rapid parity initialization process.\n", - h->scsi_host->host_no, - sd->bus, sd->target, sd->lun); + "C%d:B%d:T%d:L%d Volume is queued for rapid parity initialization process.\n", + h->scsi_host->host_no, + sd->bus, sd->target, sd->lun); break; case HPSA_LV_ENCRYPTED_NO_KEY: dev_info(&h->pdev->dev, @@ -3262,6 +3268,7 @@ static int hpsa_volume_offline(struct ctlr_info *h, /* Keep volume offline in certain cases: */ switch (ldstat) { case HPSA_LV_UNDERGOING_ERASE: + case HPSA_LV_NOT_AVAILABLE: case HPSA_LV_UNDERGOING_RPI: case HPSA_LV_PENDING_RPI: case HPSA_LV_ENCRYPTED_NO_KEY: diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 1a98bbebf15b..47c756ba8dce 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -164,6 +164,7 @@ /* Logical volume states */ #define HPSA_VPD_LV_STATUS_UNSUPPORTED 0xff #define HPSA_LV_OK 0x0 +#define HPSA_LV_NOT_AVAILABLE 0x0b #define HPSA_LV_UNDERGOING_ERASE 0x0F #define HPSA_LV_UNDERGOING_RPI 0x12 #define HPSA_LV_PENDING_RPI 0x13 From 9a4178b76a973684750d20b684bae4f57ab9a355 Mon Sep 17 00:00:00 2001 From: "shane.seymour" Date: Sat, 18 Jul 2015 11:13:09 -0500 Subject: [PATCH 44/85] hpsa: fix issues with multilun devices A regression was introduced into the hpsa driver a while back so non-zero LUNs of multi-LUN devices may no longer be presented via a SAS based Smart Array. I have not done a bisection to discover the change that caused it. The CISS firmware specification (available on sourceforge) defines an 8 byte lunid that describes devices that the Smart Array can see/present to the system. The current code in the hpsa driver attempts to find matches for non-zero LUNs with LUN 0 for a bus/target by zeroing out byte 4 of the lunid and find a match. This method is sufficient for SCSI based Smart Arrays because byte 5 is always 0. For SAS based Smart arrays byte 5 of the lunid contains the path number for a multipath device and either one or two bits (the documentation does not define how many bits are used but it appears it may be one only) that indicate if the given path number in byte 5 must always be used to access that device. Byte 5 may not always be zero. The following are lunids (spaces added for clarity) for a MSL2024 single drive library connected via a H241 Smart Array: 00 00 00 00 01 00 00 01 (changer) 00 00 00 00 00 80 00 01 (tape) In the 4th byte (counting from 0) you can see that the tape is LUN 0 and the changer is LUN 1. The 0x80 set in the 5th byte for the tape drive means the driver should force access to path 0 (the library in this case was connected to one path only anyway). After the changes we can see the following in the dmesg output: scsi 0:3:0:0: RAID HP H241 1.18 \ PQ: 0 ANSI: 5 scsi 0:2:0:0: Sequential-Access HP Ultrium 6-SCSI 354W \ PQ: 0 ANSI: 6 scsi 0:2:0:1: Medium Changer HP MSL G3 Series 8.70 \ PQ: 0 ANSI: 5 Showing that the changer is correctly identified as LUN 1 of bus 2 target 0. Before the change the changer device is not seen. Suggested-by: shane.seymour Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 07512463b990..3f1c2a88b204 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1187,17 +1187,19 @@ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, /* This is a non-zero lun of a multi-lun device. * Search through our list and find the device which - * has the same 8 byte LUN address, excepting byte 4. + * has the same 8 byte LUN address, excepting byte 4 and 5. * Assign the same bus and target for this new LUN. * Use the logical unit number from the firmware. */ memcpy(addr1, device->scsi3addr, 8); addr1[4] = 0; + addr1[5] = 0; for (i = 0; i < n; i++) { sd = h->dev[i]; memcpy(addr2, sd->scsi3addr, 8); addr2[4] = 0; - /* differ only in byte 4? */ + addr2[5] = 0; + /* differ only in byte 4 and 5? */ if (memcmp(addr1, addr2, 8) == 0) { device->bus = sd->bus; device->target = sd->target; From 2d041306b669e281427de7dd398e74335c9f5042 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Sat, 18 Jul 2015 11:13:15 -0500 Subject: [PATCH 45/85] hpsa: fix rmmod issues The driver is calling hpsa_shutdown before calling scsi_remove_host. hpsa_shutdown is disabling interrupts. scsi_remove_host can trigger I/O operations, such as SYNCHRONIZE CACHE when multipath is enabled which hang the system. Call scsi_remove_host before calling hpsa_shutdown. Reviewed-by: Kevin Barnett Reviewed-by: Scott Teel Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3f1c2a88b204..40669f8dd0df 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8272,6 +8272,14 @@ static void hpsa_remove_one(struct pci_dev *pdev) destroy_workqueue(h->rescan_ctlr_wq); destroy_workqueue(h->resubmit_wq); + /* + * Call before disabling interrupts. + * scsi_remove_host can trigger I/O operations especially + * when multipath is enabled. There can be SYNCHRONIZE CACHE + * operations which cannot complete and will hang the system. + */ + if (h->scsi_host) + scsi_remove_host(h->scsi_host); /* init_one 8 */ /* includes hpsa_free_irqs - init_one 4 */ /* includes hpsa_disable_interrupt_mode - pci_init 2 */ hpsa_shutdown(pdev); @@ -8280,8 +8288,6 @@ static void hpsa_remove_one(struct pci_dev *pdev) kfree(h->hba_inquiry_data); /* init_one 10 */ h->hba_inquiry_data = NULL; /* init_one 10 */ - if (h->scsi_host) - scsi_remove_host(h->scsi_host); /* init_one 8 */ hpsa_free_ioaccel2_sg_chain_blocks(h); hpsa_free_performant_mode(h); /* init_one 7 */ hpsa_free_sg_chain_blocks(h); /* init_one 6 */ From 5155ce5f8395730f681fe48cdc8867838e3a3f2c Mon Sep 17 00:00:00 2001 From: Dilip Kumar Uppugandla Date: Tue, 21 Jul 2015 15:07:55 -0700 Subject: [PATCH 46/85] qla2xxx: Return the fabric command state for non-task management requests Invoking get_cmd_state for qla2xxx always returns 0. Instead change it to return the actual fabric state from qla_tgt_cmd. This will help with debugging. Signed-off-by: Dilip Kumar Uppugandla Signed-off-by: Spencer Baugh Acked-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index d9a8c6084346..e8595867bb8d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -420,6 +420,12 @@ static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) { + if (!(se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { + struct qla_tgt_cmd *cmd = container_of(se_cmd, + struct qla_tgt_cmd, se_cmd); + return cmd->state; + } + return 0; } From b103918a5f21a51d12018a09919617687e584384 Mon Sep 17 00:00:00 2001 From: Sebastian Herbszt Date: Wed, 22 Jul 2015 10:53:22 +0200 Subject: [PATCH 47/85] lpfc: Use && instead of & for boolean expression Use logical instead of bitwise AND. Signed-off-by: Sebastian Herbszt Reviewed-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index ce96d5bf8ae7..759cbebed7c7 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -701,7 +701,7 @@ lpfc_work_done(struct lpfc_hba *phba) HA_RXMASK)); } } - if ((phba->sli_rev == LPFC_SLI_REV4) & + if ((phba->sli_rev == LPFC_SLI_REV4) && (!list_empty(&pring->txq))) lpfc_drain_txq(phba); /* From d32477e2a72cf9b99bb174e0f11e1b1c7834b76f Mon Sep 17 00:00:00 2001 From: Jack Wang Date: Wed, 29 Jul 2015 12:02:50 +0200 Subject: [PATCH 48/85] MAINTAINERS: update email for pm8001 Company has policy to use company email address, so update my email address to company address. Signed-off-by: Jack Wang Signed-off-by: James Bottomley --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fd6078443083..7a41c94d81dc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8038,7 +8038,7 @@ S: Supported F: drivers/scsi/pmcraid.* PMC SIERRA PM8001 DRIVER -M: xjtuwjp@gmail.com +M: Jack Wang M: lindar_liu@usish.com L: pmchba@pmcs.com L: linux-scsi@vger.kernel.org From b093d590367f6eafbec89243fabb12d4b96a9997 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:25 +0530 Subject: [PATCH 49/85] pm80xx: Updated link rate Updated 12G linkrate to libsas. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_defs.h | 1 + drivers/scsi/pm8001/pm8001_hwi.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index dc4233be52c8..f14ec6e042b9 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -57,6 +57,7 @@ enum phy_speed { PHY_SPEED_15 = 0x01, PHY_SPEED_30 = 0x02, PHY_SPEED_60 = 0x04, + PHY_SPEED_120 = 0x08, }; enum data_direction { diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 96dcc097a463..39306b1e704c 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -3263,6 +3263,10 @@ void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate) struct sas_phy *sas_phy = phy->sas_phy.phy; switch (link_rate) { + case PHY_SPEED_120: + phy->sas_phy.linkrate = SAS_LINK_RATE_12_0_GBPS; + phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_12_0_GBPS; + break; case PHY_SPEED_60: phy->sas_phy.linkrate = SAS_LINK_RATE_6_0_GBPS; phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS; From 3a1ae967741c301a5ad26665dcfb184082b969b2 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:26 +0530 Subject: [PATCH 50/85] pm80xx: Corrected device state changes in I_T_Nexus_Reset. In Nexus reset the device state request are not needed. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Acked-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_sas.c | 18 +++++++++++++----- drivers/scsi/pm8001/pm8001_sas.h | 8 ++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index b93f289b42b3..48f4627e05a4 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -975,19 +975,27 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) phy = sas_get_local_phy(dev); if (dev_is_sata(dev)) { - DECLARE_COMPLETION_ONSTACK(completion_setstate); if (scsi_is_sas_phy_local(phy)) { rc = 0; goto out; } rc = sas_phy_reset(phy, 1); + if (rc) { + PM8001_EH_DBG(pm8001_ha, + pm8001_printk("phy reset failed for device %x\n" + "with rc %d\n", pm8001_dev->device_id, rc)); + rc = TMF_RESP_FUNC_FAILED; + goto out; + } msleep(2000); rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , dev, 1, 0); - pm8001_dev->setds_completion = &completion_setstate; - rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, - pm8001_dev, 0x01); - wait_for_completion(&completion_setstate); + if (rc) { + PM8001_EH_DBG(pm8001_ha, + pm8001_printk("task abort failed %x\n" + "with rc %d\n", pm8001_dev->device_id, rc)); + rc = TMF_RESP_FUNC_FAILED; + } } else { rc = sas_phy_reset(phy, 1); msleep(2000); diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 8dd8b7840f04..c9736cc17520 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -569,6 +569,14 @@ struct pm8001_fw_image_header { #define NCQ_READ_LOG_FLAG 0x80000000 #define NCQ_ABORT_ALL_FLAG 0x40000000 #define NCQ_2ND_RLE_FLAG 0x20000000 + +/* Device states */ +#define DS_OPERATIONAL 0x01 +#define DS_PORT_IN_RESET 0x02 +#define DS_IN_RECOVERY 0x03 +#define DS_IN_ERROR 0x04 +#define DS_NON_OPERATIONAL 0x07 + /** * brief param structure for firmware flash update. */ From 842784e0d15bc21b31ce69f8f3518a8cf86084e3 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:27 +0530 Subject: [PATCH 51/85] pm80xx: Update For Thermal Page Code Thermal page code has been changed to 7 for the 12G controllers. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm80xx_hwi.c | 9 ++++++++- drivers/scsi/pm8001/pm80xx_hwi.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 05cce463ab01..dced9f7755e7 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -843,6 +843,7 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) int rc; u32 tag; u32 opc = OPC_INB_SET_CONTROLLER_CONFIG; + u32 page_code; memset(&payload, 0, sizeof(struct set_ctrl_cfg_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); @@ -851,8 +852,14 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) circularQ = &pm8001_ha->inbnd_q_tbl[0]; payload.tag = cpu_to_le32(tag); + + if (IS_SPCV_12G(pm8001_ha->pdev)) + page_code = THERMAL_PAGE_CODE_7H; + else + page_code = THERMAL_PAGE_CODE_8H; + payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) | - (THERMAL_ENABLE << 8) | THERMAL_OP_CODE; + (THERMAL_ENABLE << 8) | page_code; payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index 9970a385795d..a083cc68d937 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h @@ -177,7 +177,8 @@ /* Thermal related */ #define THERMAL_ENABLE 0x1 #define THERMAL_LOG_ENABLE 0x1 -#define THERMAL_OP_CODE 0x6 +#define THERMAL_PAGE_CODE_7H 0x6 +#define THERMAL_PAGE_CODE_8H 0x7 #define LTEMPHIL 70 #define RTEMPHIL 100 From 3b700e341144f278b8248418991c086d09b7137b Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:28 +0530 Subject: [PATCH 52/85] pm80xx: Fix for Incorrect DMA Unmapping of SG List In pm8001_ccb_task_free(), the dma unmapping is done based on ccb->n_elem value. This should be initialized to zero in the task_abort(). Otherwise, pm8001_ccb_task_free() will try for dma_unmap_sg() which is invalid for task abort and can lead to kernel crash. Changes From V1: None Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_sas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 48f4627e05a4..949198c01ced 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -790,6 +790,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, ccb->device = pm8001_dev; ccb->ccb_tag = ccb_tag; ccb->task = task; + ccb->n_elem = 0; res = PM8001_CHIP_DISP->task_abort(pm8001_ha, pm8001_dev, flag, task_tag, ccb_tag); From 3b77894b2c32ed3326c47b550f30684beb64abd3 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:29 +0530 Subject: [PATCH 53/85] pm80xx: Remove unnecessary phy disconnect while link error If the link error happens, we don't need to disconnect the phy, which will remove the drive. Instead acknowledging the controller and logging the error will be enough. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm80xx_hwi.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index dced9f7755e7..3d8b4ae06ae6 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3176,9 +3176,6 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n")); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); - sas_phy_disconnected(sas_phy); - phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: PM8001_MSG_DBG(pm8001_ha, @@ -3186,9 +3183,6 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_DISPARITY_ERROR, port_id, phy_id, 0, 0); - sas_phy_disconnected(sas_phy); - phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: PM8001_MSG_DBG(pm8001_ha, @@ -3196,9 +3190,6 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_CODE_VIOLATION, port_id, phy_id, 0, 0); - sas_phy_disconnected(sas_phy); - phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: PM8001_MSG_DBG(pm8001_ha, pm8001_printk( @@ -3206,9 +3197,6 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, port_id, phy_id, 0, 0); - sas_phy_disconnected(sas_phy); - phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_MALFUNCTION: PM8001_MSG_DBG(pm8001_ha, From 8414cd8057c29f60cda241aa489b33e4db6652f2 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:30 +0530 Subject: [PATCH 54/85] pm80xx: Add PORT RECOVERY TIMEOUT support PORT RECOVERY TIMEOUT is the maximum time between the controller's detection of the PHY down until the receipt of the ID_Frame (from the same remote SAS port). If the time expires before the ID_FRAME is received, the port is considered INVALID and can be removed. The IOP_EVENT_PORT_RECOVERY_TIMER_TMO event is reported following the IOP_EVENT_ PHY_DOWN event when the PHY/port does not recover after Port Recovery Time. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_sas.h | 2 +- drivers/scsi/pm8001/pm80xx_hwi.c | 83 ++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index c9736cc17520..27880261aafd 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -241,7 +241,7 @@ struct pm8001_chip_info { struct pm8001_port { struct asd_sas_port sas_port; u8 port_attached; - u8 wide_port_phymap; + u16 wide_port_phymap; u8 port_state; struct list_head list; }; diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 3d8b4ae06ae6..8817ce6ad4b8 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -309,6 +309,9 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET); pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset = pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET); + /* read port recover and reset timeout */ + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer = + pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER); } /** @@ -585,6 +588,12 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY, pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay); + + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0xffff0000; + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |= + PORT_RECOVERY_TIMEOUT; + pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); } /** @@ -2836,6 +2845,32 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, u32 phyId, u32 phy_op); +static void hw_event_port_recover(struct pm8001_hba_info *pm8001_ha, + void *piomb) +{ + struct hw_event_resp *pPayload = (struct hw_event_resp *)(piomb + 4); + u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate); + u8 phy_id = (u8)((phyid_npip_portstate & 0xFF0000) >> 16); + u32 lr_status_evt_portid = + le32_to_cpu(pPayload->lr_status_evt_portid); + u8 deviceType = pPayload->sas_identify.dev_type; + u8 link_rate = (u8)((lr_status_evt_portid & 0xF0000000) >> 28); + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); + struct pm8001_port *port = &pm8001_ha->port[port_id]; + + if (deviceType == SAS_END_DEVICE) { + pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id, + PHY_NOTIFY_ENABLE_SPINUP); + } + + port->wide_port_phymap |= (1U << phy_id); + pm8001_get_lrate_mode(phy, link_rate); + phy->sas_phy.oob_mode = SAS_OOB_MODE; + phy->phy_state = PHY_STATE_LINK_UP_SPCV; + phy->phy_attached = 1; +} + /** * hw_event_sas_phy_up -FW tells me a SAS phy up event. * @pm8001_ha: our hba card information @@ -2863,6 +2898,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) unsigned long flags; u8 deviceType = pPayload->sas_identify.dev_type; port->port_state = portstate; + port->wide_port_phymap |= (1U << phy_id); phy->phy_state = PHY_STATE_LINK_UP_SPCV; PM8001_MSG_DBG(pm8001_ha, pm8001_printk( "portid:%d; phyid:%d; linkrate:%d; " @@ -2988,7 +3024,6 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_port *port = &pm8001_ha->port[port_id]; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; port->port_state = portstate; - phy->phy_type = 0; phy->identify.device_type = 0; phy->phy_attached = 0; memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE); @@ -3000,9 +3035,13 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk(" PortInvalid portID %d\n", port_id)); PM8001_MSG_DBG(pm8001_ha, pm8001_printk(" Last phy Down and port invalid\n")); - port->port_attached = 0; - pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, - port_id, phy_id, 0, 0); + if (phy->phy_type & PORT_TYPE_SATA) { + phy->phy_type = 0; + port->port_attached = 0; + pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, + port_id, phy_id, 0, 0); + } + sas_phy_disconnected(&phy->sas_phy); break; case PORT_IN_RESET: PM8001_MSG_DBG(pm8001_ha, @@ -3010,22 +3049,26 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; case PORT_NOT_ESTABLISHED: PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n")); + pm8001_printk(" Phy Down and PORT_NOT_ESTABLISHED\n")); port->port_attached = 0; break; case PORT_LOSTCOMM: PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" phy Down and PORT_LOSTCOMM\n")); + pm8001_printk(" Phy Down and PORT_LOSTCOMM\n")); PM8001_MSG_DBG(pm8001_ha, pm8001_printk(" Last phy Down and port invalid\n")); - port->port_attached = 0; - pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, - port_id, phy_id, 0, 0); + if (phy->phy_type & PORT_TYPE_SATA) { + port->port_attached = 0; + phy->phy_type = 0; + pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, + port_id, phy_id, 0, 0); + } + sas_phy_disconnected(&phy->sas_phy); break; default: port->port_attached = 0; PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" phy Down and(default) = 0x%x\n", + pm8001_printk(" Phy Down and(default) = 0x%x\n", portstate)); break; @@ -3091,7 +3134,7 @@ static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) */ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) { - unsigned long flags; + unsigned long flags, i; struct hw_event_resp *pPayload = (struct hw_event_resp *)(piomb + 4); u32 lr_status_evt_portid = @@ -3104,9 +3147,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8); u8 status = (u8)((lr_status_evt_portid & 0x0F000000) >> 24); - struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; + struct pm8001_port *port = &pm8001_ha->port[port_id]; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; PM8001_MSG_DBG(pm8001_ha, pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n", @@ -3132,7 +3175,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) case HW_EVENT_PHY_DOWN: PM8001_MSG_DBG(pm8001_ha, pm8001_printk("HW_EVENT_PHY_DOWN\n")); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); + if (phy->phy_type & PORT_TYPE_SATA) + sas_ha->notify_phy_event(&phy->sas_phy, + PHYE_LOSS_OF_SIGNAL); phy->phy_attached = 0; phy->phy_state = 0; hw_event_phy_down(pm8001_ha, piomb); @@ -3252,13 +3297,19 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PORT_RECOVERY_TIMER_TMO, port_id, phy_id, 0, 0); - sas_phy_disconnected(sas_phy); - phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { + if (port->wide_port_phymap & (1 << i)) { + phy = &pm8001_ha->phy[i]; + sas_ha->notify_phy_event(&phy->sas_phy, + PHYE_LOSS_OF_SIGNAL); + port->wide_port_phymap &= ~(1 << i); + } + } break; case HW_EVENT_PORT_RECOVER: PM8001_MSG_DBG(pm8001_ha, pm8001_printk("HW_EVENT_PORT_RECOVER\n")); + hw_event_port_recover(pm8001_ha, piomb); break; case HW_EVENT_PORT_RESET_COMPLETE: PM8001_MSG_DBG(pm8001_ha, From 27ecfa5e79bfc2e4efca67a6077080acab546a4a Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:31 +0530 Subject: [PATCH 55/85] pm80xx: Handling Invalid SSP Response frame The request has to be retried incase if the length of the SSP Response IU is invalid. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm80xx_hwi.c | 7 +++++++ drivers/scsi/pm8001/pm80xx_hwi.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 8817ce6ad4b8..0e1628f2018e 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -1609,6 +1609,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; + case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME: + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n")); + ts->resp = SAS_TASK_COMPLETE; + ts->stat = SAS_OPEN_REJECT; + ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index a083cc68d937..7a443bad6163 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h @@ -1175,7 +1175,7 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; #define IO_XFER_ERROR_INTERNAL_CRC_ERROR 0x54 #define MPI_IO_RQE_BUSY_FULL 0x55 #define IO_XFER_ERR_EOB_DATA_OVERRUN 0x56 -#define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME 0x57 +#define IO_XFER_ERROR_INVALID_SSP_RSP_FRAME 0x57 #define IO_OPEN_CNX_ERROR_OPEN_PREEMPTED 0x58 #define MPI_ERR_IO_RESOURCE_UNAVAILABLE 0x1004 From 1cd129918f14f42f8b1940096dba629ce7e7a243 Mon Sep 17 00:00:00 2001 From: Viswas G Date: Tue, 11 Aug 2015 15:06:32 +0530 Subject: [PATCH 56/85] pm80xx: Bump pm80xx driver version to 0.1.38 Bump pm80xx driver version to 0.1.38. Signed-off-by: Viswas G Reviewed-by: Suresh Thiagarajan Reviewed-by: Hannes Reinecke Reviewed-by: Jack Wang Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_sas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 27880261aafd..e2e97db38ae8 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -58,7 +58,7 @@ #include "pm8001_defs.h" #define DRV_NAME "pm80xx" -#define DRV_VERSION "0.1.37" +#define DRV_VERSION "0.1.38" #define PM8001_FAIL_LOGGING 0x01 /* Error message logging */ #define PM8001_INIT_LOGGING 0x02 /* driver init logging */ #define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */ From 709c75b5a2411c31e5a649a2cd6d4866dd11f456 Mon Sep 17 00:00:00 2001 From: "jiang.biao2@zte.com.cn" Date: Fri, 31 Jul 2015 17:52:10 +0800 Subject: [PATCH 57/85] scsi_error: should not get sense for timeout IO in scsi error handler scsi_error: should not get sense for timeout IO in scsi error handler When an IO timeout occurs, the IO will be aborted in scsi_abort_command() and SCSI_EH_ABORT_SCHEDULED will be set. Because of that, the SCSI_EH_CANCEL_CMD will be clear in scsi_eh_scmd_add(). So when scsi error handler starts, it will get sense for this timeout IO and the scmd of the IO request will be reused. In that case, the scmd may be double released when racing with io_done(), which will result in crash. SO SCSI_EH_ABORT_SCHEDULED should also be checked when getting sense. The bug maybe reproduced when the link between host and disk is unstable. Signed-off-by: Jiang Biao Signed-off-by: Long Chun Reviewed-by: Tan Hu Reviewed-by: Chen Donghai Reviewed-by: Cai Qu Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d7d28061b31d..3aacd96d63f3 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1160,8 +1160,13 @@ int scsi_eh_get_sense(struct list_head *work_q, struct Scsi_Host *shost; int rtn; + /* + * If SCSI_EH_ABORT_SCHEDULED has been set, it is timeout IO, + * should not get sense. + */ list_for_each_entry_safe(scmd, next, work_q, eh_entry) { if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || + (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) || SCSI_SENSE_VALID(scmd)) continue; From f299c7c2ab5df78e3201af34e596e8a3ba4d2791 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 4 Aug 2015 13:37:51 -0400 Subject: [PATCH 58/85] qla2xxx: Add serdes register read/write support for ISP25xx. Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 26ca18c3fa6a..6e22052afc89 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2847,7 +2847,8 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA2031(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && + !IS_QLA27XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, @@ -2885,7 +2886,8 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA2031(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && + !IS_QLA27XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, From 17cac3a175a02cd1ae21f9183b09f30a719832df Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 4 Aug 2015 13:37:52 -0400 Subject: [PATCH 59/85] qla2xxx: Handle AEN8014 incoming port logout. When we get logged out, mark the port lost and set dpc flag for relogin. Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 35 +++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 583d52aae79d..05d8cf016543 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -26,7 +26,7 @@ * | | | 0x3036,0x3038 | * | | | 0x303a | * | DPC Thread | 0x4023 | 0x4002,0x4013 | - * | Async Events | 0x5087 | 0x502b-0x502f | + * | Async Events | 0x508a | 0x502b-0x502f | * | | | 0x5047 | * | | | 0x5084,0x5075 | * | | | 0x503d,0x5044 | diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2cb0fba38c9e..b2b93dfbffd3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -560,6 +560,17 @@ qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry) return ret; } +static inline fc_port_t * +qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id) +{ + fc_port_t *fcport; + + list_for_each_entry(fcport, &vha->vp_fcports, list) + if (fcport->loop_id == loop_id) + return fcport; + return NULL; +} + /** * qla2x00_async_event() - Process aynchronous events. * @ha: SCSI driver HA context @@ -897,11 +908,29 @@ skip_rio: (mb[1] != 0xffff)) && vha->vp_idx != (mb[3] & 0xff)) break; - /* Global event -- port logout or port unavailable. */ - if (mb[1] == 0xffff && mb[2] == 0x7) { + if (mb[2] == 0x7) { ql_dbg(ql_dbg_async, vha, 0x5010, - "Port unavailable %04x %04x %04x.\n", + "Port %s %04x %04x %04x.\n", + mb[1] == 0xffff ? "unavailable" : "logout", mb[1], mb[2], mb[3]); + + if (mb[1] == 0xffff) + goto global_port_update; + + /* Port logout */ + fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]); + if (!fcport) + break; + if (atomic_read(&fcport->state) != FCS_ONLINE) + break; + ql_dbg(ql_dbg_async, vha, 0x508a, + "Marking port lost loopid=%04x portid=%06x.\n", + fcport->loop_id, fcport->d_id.b24); + qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1); + break; + +global_port_update: + /* Port unavailable. */ ql_log(ql_log_warn, vha, 0x505e, "Link is offline.\n"); From cc790764391a68511cf6a7e4dd18eeb6e7640233 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 4 Aug 2015 13:37:53 -0400 Subject: [PATCH 60/85] qla2xxx: Use ssdid to gate semaphore manipulation. Execute qla25xx_manipulate_risc_semaphore() only for ssdid 0x0175 and 0x0240. Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5a5ca43e5e90..f64bb6b7a08f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1272,14 +1272,14 @@ qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data) static void qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha) { - struct qla_hw_data *ha = vha->hw; uint32_t wd32 = 0; uint delta_msec = 100; uint elapsed_msec = 0; uint timeout_msec; ulong n; - if (!IS_QLA25XX(ha) && !IS_QLA2031(ha)) + if (vha->hw->pdev->subsystem_device != 0x0175 && + vha->hw->pdev->subsystem_device != 0x0240) return; attempt: From 8dd7e3a55949f17fecba4aedb2cb943b153e5e55 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 4 Aug 2015 13:37:54 -0400 Subject: [PATCH 61/85] qla2xxx: Pause risc before manipulating risc semaphore. Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f64bb6b7a08f..014f44f7a7c4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1282,6 +1282,9 @@ qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha) vha->hw->pdev->subsystem_device != 0x0240) return; + WRT_REG_DWORD(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE); + udelay(100); + attempt: timeout_msec = TIMEOUT_SEMAPHORE; n = timeout_msec / delta_msec; From d6b9b42b49518c30df9de92ce499f005d336e97b Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Tue, 4 Aug 2015 13:37:55 -0400 Subject: [PATCH 62/85] qla2xxx: Add adapter checks for FAWWN functionality. Signed-off-by: Saurav Kashyap Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 30 ++++++++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ac88c4e7cf13..cbcc6fc9f562 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3164,6 +3164,7 @@ struct qla_hw_data { #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)) /* HBA serial number */ uint8_t serial0; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 6e22052afc89..62a83e39f6ed 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1135,20 +1135,22 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, vha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff; } /* If FA-WWN supported */ - if (mcp->mb[7] & BIT_14) { - vha->port_name[0] = MSB(mcp->mb[16]); - vha->port_name[1] = LSB(mcp->mb[16]); - vha->port_name[2] = MSB(mcp->mb[17]); - vha->port_name[3] = LSB(mcp->mb[17]); - vha->port_name[4] = MSB(mcp->mb[18]); - vha->port_name[5] = LSB(mcp->mb[18]); - vha->port_name[6] = MSB(mcp->mb[19]); - vha->port_name[7] = LSB(mcp->mb[19]); - fc_host_port_name(vha->host) = - wwn_to_u64(vha->port_name); - ql_dbg(ql_dbg_mbx, vha, 0x10ca, - "FA-WWN acquired %016llx\n", - wwn_to_u64(vha->port_name)); + if (IS_FAWWN_CAPABLE(vha->hw)) { + if (mcp->mb[7] & BIT_14) { + vha->port_name[0] = MSB(mcp->mb[16]); + vha->port_name[1] = LSB(mcp->mb[16]); + vha->port_name[2] = MSB(mcp->mb[17]); + vha->port_name[3] = LSB(mcp->mb[17]); + vha->port_name[4] = MSB(mcp->mb[18]); + vha->port_name[5] = LSB(mcp->mb[18]); + vha->port_name[6] = MSB(mcp->mb[19]); + vha->port_name[7] = LSB(mcp->mb[19]); + fc_host_port_name(vha->host) = + wwn_to_u64(vha->port_name); + ql_dbg(ql_dbg_mbx, vha, 0x10ca, + "FA-WWN acquired %016llx\n", + wwn_to_u64(vha->port_name)); + } } } From 8fbdac8c70d378016f568106f09fb3ff153a47c3 Mon Sep 17 00:00:00 2001 From: Hiral Patel Date: Tue, 4 Aug 2015 13:37:56 -0400 Subject: [PATCH 63/85] qla2xxx: Do not crash system for sp ref count zero Aovid crashing the system in the scenario where firmware just completes the command and it can not find the command during abort mailbox processing. This scenario can lead to sp reference counter being zero. Instead of crashing the system, use WARN_ON to print warning in log file. Signed-off-by: Hiral Patel Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5a5166bd4287..8763c12cb6c2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -656,7 +656,7 @@ qla2x00_sp_compl(void *data, void *ptr, int res) "SP reference-count to ZERO -- sp=%p cmd=%p.\n", sp, GET_CMD_SP(sp)); if (ql2xextended_error_logging & ql_dbg_io) - BUG(); + WARN_ON(atomic_read(&sp->ref_count) == 0); return; } if (!atomic_dec_and_test(&sp->ref_count)) From c7bc4cae0d5c9703d8b15fcc0fd53b86b135bde8 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Tue, 4 Aug 2015 13:37:57 -0400 Subject: [PATCH 64/85] qla2xxx: Do not reset adapter if SRB handle is in range. If an SRB is NULL but the handle is in range just drop the command instead of also resetting the adapter. If the handle is in range then the command was valid at some point and may have been aborted. Resetting the adapter can lead to extended recovery times in this case. Signed-off-by: Chad Dupuis Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 20 ++++++++++++-------- drivers/scsi/qla2xxx/qla_os.c | 4 ++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 05d8cf016543..c6e51c6cd3dc 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -19,7 +19,7 @@ * | Device Discovery | 0x2016 | 0x2020-0x2022, | * | | | 0x2011-0x2012, | * | | | 0x2099-0x20a4 | - * | Queue Command and IO tracing | 0x3059 | 0x300b | + * | Queue Command and IO tracing | 0x3075 | 0x300b | * | | | 0x3027-0x3028 | * | | | 0x303d-0x3041 | * | | | 0x302d,0x3033 | diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b2b93dfbffd3..08190e07c640 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2073,14 +2073,18 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) } /* Validate handle. */ - if (handle < req->num_outstanding_cmds) + if (handle < req->num_outstanding_cmds) { sp = req->outstanding_cmds[handle]; - else - sp = NULL; - - if (sp == NULL) { + if (!sp) { + ql_dbg(ql_dbg_io, vha, 0x3075, + "%s(%ld): Already returned command for status handle (0x%x).\n", + __func__, vha->host_no, sts->handle); + return; + } + } else { ql_dbg(ql_dbg_io, vha, 0x3017, - "Invalid status handle (0x%x).\n", sts->handle); + "Invalid status handle, out of range (0x%x).\n", + sts->handle); if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) { if (IS_P3P_TYPE(ha)) @@ -2367,12 +2371,12 @@ out: ql_dbg(ql_dbg_io, fcport->vha, 0x3022, "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x " - "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n", + "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n", comp_status, scsi_status, res, vha->host_no, cp->device->id, cp->device->lun, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id, cp->cmnd, scsi_bufflen(cp), rsp_info_len, - resid_len, fw_resid_len); + resid_len, fw_resid_len, sp, cp); if (rsp->status_srb == NULL) sp->done(ha, sp, res); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8763c12cb6c2..f70809feca90 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -958,8 +958,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_dbg(ql_dbg_taskm, vha, 0x8002, - "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p\n", - vha->host_no, id, lun, sp, cmd); + "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n", + vha->host_no, id, lun, sp, cmd, sp->handle); /* Get a reference to the sp and drop the lock.*/ sp_get(sp); From fd49a540ead94ce5769f6eb2028e97577739e24b Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Tue, 4 Aug 2015 13:37:58 -0400 Subject: [PATCH 65/85] qla2xxx: Do not reset ISP for error entry with an out of range handle. Instead of resetting the adapter wait for the login to timeout and retry. Resetting the adapter can cause extended path recovery times. Signed-off-by: Chad Dupuis Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 08190e07c640..ccf6a7f99024 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2473,13 +2473,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) } fatal: ql_log(ql_log_warn, vha, 0x5030, - "Error entry - invalid handle/queue.\n"); - - if (IS_P3P_TYPE(ha)) - set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags); - else - set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); + "Error entry - invalid handle/queue (%04x).\n", que); } /** From 03aa868c1b7b2633a4faa97b28c40e64c91a8e7f Mon Sep 17 00:00:00 2001 From: Sawan Chandak Date: Tue, 4 Aug 2015 13:37:59 -0400 Subject: [PATCH 66/85] qla2xxx: Add support to show MPI and PEP FW version for ISP27xx. Signed-off-by: Sawan Chandak Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 19 ++++++++++++++++++- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 13 ++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2087b73927ce..b352d234b70a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1345,7 +1345,8 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) && + !IS_QLA27XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", @@ -1534,6 +1535,20 @@ qla2x00_allow_cna_fw_dump_store(struct device *dev, return strlen(buf); } +static ssize_t +qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA27XX(ha)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", + ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]); +} + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -1578,6 +1593,7 @@ static DEVICE_ATTR(fw_dump_size, S_IRUGO, qla2x00_fw_dump_size_show, NULL); static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR, qla2x00_allow_cna_fw_dump_show, qla2x00_allow_cna_fw_dump_store); +static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL); struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_driver_version, @@ -1611,6 +1627,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_diag_megabytes, &dev_attr_fw_dump_size, &dev_attr_allow_cna_fw_dump, + &dev_attr_pep_version, NULL, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index cbcc6fc9f562..e8073917e7a3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3287,6 +3287,7 @@ struct qla_hw_data { uint8_t mpi_version[3]; uint32_t mpi_capabilities; uint8_t phy_version[3]; + uint8_t pep_version[3]; /* Firmware dump template */ void *fw_dump_template; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 62a83e39f6ed..97b5bd569d03 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -555,7 +555,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) if (IS_FWI2_CAPABLE(ha)) mcp->in_mb |= MBX_17|MBX_16|MBX_15; if (IS_QLA27XX(ha)) - mcp->in_mb |= MBX_21|MBX_20|MBX_19|MBX_18; + mcp->in_mb |= MBX_23 | MBX_22 | MBX_21 | MBX_20 | MBX_19 | + MBX_18 | MBX_14 | MBX_13 | MBX_11 | MBX_10 | MBX_9 | MBX_8; + mcp->flags = 0; mcp->tov = MBX_TOV_SECONDS; rval = qla2x00_mailbox_command(vha, mcp); @@ -571,6 +573,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_memory_size = 0x1FFFF; /* Defaults to 128KB. */ else ha->fw_memory_size = (mcp->mb[5] << 16) | mcp->mb[4]; + if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) || IS_QLA8044(ha)) { ha->mpi_version[0] = mcp->mb[10] & 0xff; ha->mpi_version[1] = mcp->mb[11] >> 8; @@ -580,6 +583,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->phy_version[1] = mcp->mb[9] >> 8; ha->phy_version[2] = mcp->mb[9] & 0xff; } + if (IS_FWI2_CAPABLE(ha)) { ha->fw_attributes_h = mcp->mb[15]; ha->fw_attributes_ext[0] = mcp->mb[16]; @@ -591,7 +595,14 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) "%s: Ext_FwAttributes Upper: 0x%x, Lower: 0x%x.\n", __func__, mcp->mb[17], mcp->mb[16]); } + if (IS_QLA27XX(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; + ha->pep_version[0] = mcp->mb[13] & 0xff; + ha->pep_version[1] = mcp->mb[14] >> 8; + ha->pep_version[2] = mcp->mb[14] & 0xff; ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18]; ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20]; } From 96219424f2c7b767e42ccf203df40d7df677a5e3 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Tue, 4 Aug 2015 13:38:00 -0400 Subject: [PATCH 67/85] qla2xxx: Remove decrement of sp reference count in abort handler. Fix for memory leak when command is not found by firmware due to mismatch in sp reference count. Signed-off-by: Chad Dupuis Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f70809feca90..95bee6807f46 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -967,14 +967,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&ha->hardware_lock, flags); rval = ha->isp_ops->abort_command(sp); if (rval) { - if (rval == QLA_FUNCTION_PARAMETER_ERROR) { - /* - * Decrement the ref_count since we can't find the - * command - */ - atomic_dec(&sp->ref_count); + if (rval == QLA_FUNCTION_PARAMETER_ERROR) ret = SUCCESS; - } else + else ret = FAILED; ql_dbg(ql_dbg_taskm, vha, 0x8003, From 63e322aaa6a00536055558ac1307b2919ee57aef Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Tue, 4 Aug 2015 13:38:01 -0400 Subject: [PATCH 68/85] qla2xxx: do not clear slot in outstanding cmd array Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 95bee6807f46..0b90fac255d3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -981,12 +981,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } spin_lock_irqsave(&ha->hardware_lock, flags); - /* - * Clear the slot in the oustanding_cmds array if we can't find the - * command to reclaim the resources. - */ - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - vha->req->outstanding_cmds[sp->handle] = NULL; sp->done(ha, sp, 0); spin_unlock_irqrestore(&ha->hardware_lock, flags); From a1d0285ecb61800a9e6808f716b880eae95f14bc Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Tue, 4 Aug 2015 13:38:02 -0400 Subject: [PATCH 69/85] qla2xxx: Fix missing device login retries. On certain conditions, login failures will just invoke qla2x00_mark_device_lost() with the intend to do login again; but if login_retry has been set already, that would fail to set the relogin needed flag which is required to wakeup the DPC to retry. Signed-off-by: Arun Easi Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0b90fac255d3..0d0ff33d010f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3258,9 +3258,10 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, if (!do_login) return; + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + if (fcport->login_retry == 0) { fcport->login_retry = vha->hw->login_retry_count; - set_bit(RELOGIN_NEEDED, &vha->dpc_flags); ql_dbg(ql_dbg_disc, vha, 0x2067, "Port login retry %8phN, id = 0x%04x retry cnt=%d.\n", From 2b48992f656e109b9d7357cedc0406b50ec82c22 Mon Sep 17 00:00:00 2001 From: Sawan Chandak Date: Tue, 4 Aug 2015 13:38:03 -0400 Subject: [PATCH 70/85] qla2xxx: Add pci device id 0x2261. Signed-off-by: Sawan Chandak Signed-off-by: Himanshu Madhani Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 7 +++++-- drivers/scsi/qla2xxx/qla_os.c | 11 ++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e8073917e7a3..a72b29f4dd79 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3059,6 +3059,7 @@ struct qla_hw_data { #define PCI_DEVICE_ID_QLOGIC_ISP2031 0x2031 #define PCI_DEVICE_ID_QLOGIC_ISP2071 0x2071 #define PCI_DEVICE_ID_QLOGIC_ISP2271 0x2271 +#define PCI_DEVICE_ID_QLOGIC_ISP2261 0x2261 uint32_t device_type; #define DT_ISP2100 BIT_0 @@ -3082,7 +3083,8 @@ struct qla_hw_data { #define DT_ISP8044 BIT_18 #define DT_ISP2071 BIT_19 #define DT_ISP2271 BIT_20 -#define DT_ISP_LAST (DT_ISP2271 << 1) +#define DT_ISP2261 BIT_21 +#define DT_ISP_LAST (DT_ISP2261 << 1) #define DT_T10_PI BIT_25 #define DT_IIDMA BIT_26 @@ -3114,6 +3116,7 @@ struct qla_hw_data { #define IS_QLAFX00(ha) (DT_MASK(ha) & DT_ISPFX00) #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_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) @@ -3122,7 +3125,7 @@ struct qla_hw_data { #define IS_QLA25XX(ha) (IS_QLA2532(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)) +#define IS_QLA27XX(ha) (IS_QLA2071(ha) || IS_QLA2271(ha) || IS_QLA2261(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) || \ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0d0ff33d010f..913a72506748 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2208,6 +2208,13 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_IIDMA; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; + case PCI_DEVICE_ID_QLOGIC_ISP2261: + ha->device_type |= DT_ISP2261; + ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; + break; } if (IS_QLA82XX(ha)) @@ -2285,7 +2292,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001 || 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_ISP2271 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261) { bars = pci_select_bars(pdev, IORESOURCE_MEM); mem_only = 1; ql_dbg_pci(ql_dbg_init, pdev, 0x0007, @@ -5697,6 +5705,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8044) }, { 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) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); From ef2a388dfce6ddc2fd0d1d798a8974396f6b6a22 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Tue, 4 Aug 2015 13:38:04 -0400 Subject: [PATCH 71/85] qla2xxx: Update driver version to 8.07.00.26-k Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 2ed9ab90a455..6d31faa8c57b 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.07.00.18-k" +#define QLA2XXX_VERSION "8.07.00.26-k" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 7 From 5cdac81a870f3bb65c50d3f5566a86fb086118d2 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Thu, 13 Aug 2015 21:47:34 -0500 Subject: [PATCH 72/85] cxlflash: Base error recovery support Introduce support for enhanced I/O error handling. A device state is added to track 3 possible states of the device: Normal - the device is operating normally and is fully operational Limbo - the device is in a reset/recovery scenario and its operational status is paused Failed/terminating - the device has either failed to be reset/recovered or is being terminated (removed); it is no longer operational All operations are allowed when the device is operating normally. When the device transitions to limbo state, I/O must be paused. To help accomplish this, a wait queue is introduced where existing and new threads can wait until the device is no longer in limbo. When coming out of limbo, threads need to check the state and error out gracefully when encountering the failed state. When the device transitions to the failed/terminating state, normal operations are no longer allowed. Only specially designated operations related to graceful cleanup are permitted. Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reviewed-by: Daniel Axtens Reviewed-by: Michael Neuling Reviewed-by: Wen Xiong Reviewed-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/cxlflash/Kconfig | 2 +- drivers/scsi/cxlflash/common.h | 11 +- drivers/scsi/cxlflash/main.c | 174 ++++++++++++++++++++++++++++++-- drivers/scsi/cxlflash/main.h | 6 +- drivers/scsi/cxlflash/sislite.h | 0 5 files changed, 177 insertions(+), 16 deletions(-) mode change 100755 => 100644 drivers/scsi/cxlflash/sislite.h diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig index c7075084cfdb..c052104e523e 100644 --- a/drivers/scsi/cxlflash/Kconfig +++ b/drivers/scsi/cxlflash/Kconfig @@ -4,7 +4,7 @@ config CXLFLASH tristate "Support for IBM CAPI Flash" - depends on PCI && SCSI && CXL + depends on PCI && SCSI && CXL && EEH default m help Allows CAPI Accelerated IO to Flash diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index 5f43608dc8a1..ffdbc572d180 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -76,6 +76,12 @@ enum cxlflash_init_state { INIT_STATE_SCSI }; +enum cxlflash_state { + STATE_NORMAL, /* Normal running state, everything good */ + STATE_LIMBO, /* Limbo running state, trying to reset/recover */ + STATE_FAILTERM /* Failed/terminating state, error out users/threads */ +}; + /* * Each context has its own set of resource handles that is visible * only from that context. @@ -91,8 +97,6 @@ struct cxlflash_cfg { ulong cxlflash_regs_pci; - wait_queue_head_t eeh_waitq; - struct work_struct work_q; enum cxlflash_init_state init_state; enum cxlflash_lr_state lr_state; @@ -105,7 +109,8 @@ struct cxlflash_cfg { wait_queue_head_t tmf_waitq; bool tmf_active; - u8 err_recovery_active:1; + wait_queue_head_t limbo_waitq; + enum cxlflash_state state; }; struct afu_cmd { diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 0720d2f13c2a..3ae8dca236ef 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -353,6 +353,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; struct afu *afu = cfg->afu; struct pci_dev *pdev = cfg->dev; + struct device *dev = &cfg->dev->dev; struct afu_cmd *cmd; u32 port_sel = scp->device->channel + 1; int nseg, i, ncount; @@ -380,6 +381,21 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) } spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + switch (cfg->state) { + case STATE_LIMBO: + dev_dbg_ratelimited(dev, "%s: device in limbo!\n", __func__); + rc = SCSI_MLQUEUE_HOST_BUSY; + goto out; + case STATE_FAILTERM: + dev_dbg_ratelimited(dev, "%s: device has failed!\n", __func__); + scp->result = (DID_NO_CONNECT << 16); + scp->scsi_done(scp); + rc = 0; + goto out; + default: + break; + } + cmd = cxlflash_cmd_checkout(afu); if (unlikely(!cmd)) { pr_err("%s: could not get a free command\n", __func__); @@ -455,9 +471,21 @@ static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp) get_unaligned_be32(&((u32 *)scp->cmnd)[2]), get_unaligned_be32(&((u32 *)scp->cmnd)[3])); - rcr = send_tmf(afu, scp, TMF_LUN_RESET); - if (unlikely(rcr)) + switch (cfg->state) { + case STATE_NORMAL: + rcr = send_tmf(afu, scp, TMF_LUN_RESET); + if (unlikely(rcr)) + rc = FAILED; + break; + case STATE_LIMBO: + wait_event(cfg->limbo_waitq, cfg->state != STATE_LIMBO); + if (cfg->state == STATE_NORMAL) + break; + /* fall through */ + default: rc = FAILED; + break; + } pr_debug("%s: returning rc=%d\n", __func__, rc); return rc; @@ -487,11 +515,29 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) get_unaligned_be32(&((u32 *)scp->cmnd)[2]), get_unaligned_be32(&((u32 *)scp->cmnd)[3])); - rcr = cxlflash_afu_reset(cfg); - if (rcr == 0) - rc = SUCCESS; - else + switch (cfg->state) { + case STATE_NORMAL: + cfg->state = STATE_LIMBO; + scsi_block_requests(cfg->host); + + rcr = cxlflash_afu_reset(cfg); + if (rcr) { + rc = FAILED; + cfg->state = STATE_FAILTERM; + } else + cfg->state = STATE_NORMAL; + wake_up_all(&cfg->limbo_waitq); + scsi_unblock_requests(cfg->host); + break; + case STATE_LIMBO: + wait_event(cfg->limbo_waitq, cfg->state != STATE_LIMBO); + if (cfg->state == STATE_NORMAL) + break; + /* fall through */ + default: rc = FAILED; + break; + } pr_debug("%s: returning rc=%d\n", __func__, rc); return rc; @@ -642,7 +688,7 @@ static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg) struct pci_dev *pdev = cfg->dev; if (pci_channel_offline(pdev)) - wait_event_timeout(cfg->eeh_waitq, + wait_event_timeout(cfg->limbo_waitq, !pci_channel_offline(pdev), CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT); } @@ -825,6 +871,8 @@ static void cxlflash_remove(struct pci_dev *pdev) !cfg->tmf_active); spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); + cfg->state = STATE_FAILTERM; + switch (cfg->init_state) { case INIT_STATE_SCSI: scsi_remove_host(cfg->host); @@ -1879,6 +1927,8 @@ static int init_afu(struct cxlflash_cfg *cfg) struct afu *afu = cfg->afu; struct device *dev = &cfg->dev->dev; + cxl_perst_reloads_same_image(cfg->cxl_afu, true); + rc = init_mc(cfg); if (rc) { dev_err(dev, "%s: call to init_mc failed, rc=%d!\n", @@ -2021,6 +2071,12 @@ void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd) * the sync. This design point requires calling threads to not be on interrupt * context due to the possibility of sleeping during concurrent sync operations. * + * AFU sync operations are only necessary and allowed when the device is + * operating normally. When not operating normally, sync requests can occur as + * part of cleaning up resources associated with an adapter prior to removal. + * In this scenario, these requests are simply ignored (safe due to the AFU + * going away). + * * Return: * 0 on success * -1 on failure @@ -2028,11 +2084,17 @@ void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd) int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, res_hndl_t res_hndl_u, u8 mode) { + struct cxlflash_cfg *cfg = afu->parent; struct afu_cmd *cmd = NULL; int rc = 0; int retry_cnt = 0; static DEFINE_MUTEX(sync_active); + if (cfg->state != STATE_NORMAL) { + pr_debug("%s: Sync not required! (%u)\n", __func__, cfg->state); + return 0; + } + mutex_lock(&sync_active); retry: cmd = cxlflash_cmd_checkout(afu); @@ -2116,12 +2178,17 @@ int cxlflash_afu_reset(struct cxlflash_cfg *cfg) */ static void cxlflash_worker_thread(struct work_struct *work) { - struct cxlflash_cfg *cfg = - container_of(work, struct cxlflash_cfg, work_q); + struct cxlflash_cfg *cfg = container_of(work, struct cxlflash_cfg, + work_q); struct afu *afu = cfg->afu; int port; ulong lock_flags; + /* Avoid MMIO if the device has failed */ + + if (cfg->state != STATE_NORMAL) + return; + spin_lock_irqsave(cfg->host->host_lock, lock_flags); if (cfg->lr_state == LINK_RESET_REQUIRED) { @@ -2200,10 +2267,9 @@ static int cxlflash_probe(struct pci_dev *pdev, cfg->dev = pdev; cfg->dev_id = (struct pci_device_id *)dev_id; cfg->mcctx = NULL; - cfg->err_recovery_active = 0; init_waitqueue_head(&cfg->tmf_waitq); - init_waitqueue_head(&cfg->eeh_waitq); + init_waitqueue_head(&cfg->limbo_waitq); INIT_WORK(&cfg->work_q, cxlflash_worker_thread); cfg->lr_state = LINK_RESET_INVALID; @@ -2259,6 +2325,91 @@ out_remove: goto out; } +/** + * cxlflash_pci_error_detected() - called when a PCI error is detected + * @pdev: PCI device struct. + * @state: PCI channel state. + * + * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT + */ +static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); + struct device *dev = &cfg->dev->dev; + + dev_dbg(dev, "%s: pdev=%p state=%u\n", __func__, pdev, state); + + switch (state) { + case pci_channel_io_frozen: + cfg->state = STATE_LIMBO; + + /* Turn off legacy I/O */ + scsi_block_requests(cfg->host); + + term_mc(cfg, UNDO_START); + stop_afu(cfg); + + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + cfg->state = STATE_FAILTERM; + wake_up_all(&cfg->limbo_waitq); + scsi_unblock_requests(cfg->host); + return PCI_ERS_RESULT_DISCONNECT; + default: + break; + } + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * cxlflash_pci_slot_reset() - called when PCI slot has been reset + * @pdev: PCI device struct. + * + * This routine is called by the pci error recovery code after the PCI + * slot has been reset, just before we should resume normal operations. + * + * Return: PCI_ERS_RESULT_RECOVERED or PCI_ERS_RESULT_DISCONNECT + */ +static pci_ers_result_t cxlflash_pci_slot_reset(struct pci_dev *pdev) +{ + int rc = 0; + struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); + struct device *dev = &cfg->dev->dev; + + dev_dbg(dev, "%s: pdev=%p\n", __func__, pdev); + + rc = init_afu(cfg); + if (unlikely(rc)) { + dev_err(dev, "%s: EEH recovery failed! (%d)\n", __func__, rc); + return PCI_ERS_RESULT_DISCONNECT; + } + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * cxlflash_pci_resume() - called when normal operation can resume + * @pdev: PCI device struct + */ +static void cxlflash_pci_resume(struct pci_dev *pdev) +{ + struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); + struct device *dev = &cfg->dev->dev; + + dev_dbg(dev, "%s: pdev=%p\n", __func__, pdev); + + cfg->state = STATE_NORMAL; + wake_up_all(&cfg->limbo_waitq); + scsi_unblock_requests(cfg->host); +} + +static const struct pci_error_handlers cxlflash_err_handler = { + .error_detected = cxlflash_pci_error_detected, + .slot_reset = cxlflash_pci_slot_reset, + .resume = cxlflash_pci_resume, +}; + /* * PCI device structure */ @@ -2267,6 +2418,7 @@ static struct pci_driver cxlflash_driver = { .id_table = cxlflash_pci_table, .probe = cxlflash_probe, .remove = cxlflash_remove, + .err_handler = &cxlflash_err_handler, }; /** diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h index 7f890ccf3289..cf0e80938b13 100644 --- a/drivers/scsi/cxlflash/main.h +++ b/drivers/scsi/cxlflash/main.h @@ -22,7 +22,7 @@ #define CXLFLASH_NAME "cxlflash" #define CXLFLASH_ADAPTER_NAME "IBM POWER CXL Flash Adapter" -#define CXLFLASH_DRIVER_DATE "(June 2, 2015)" +#define CXLFLASH_DRIVER_DATE "(August 13, 2015)" #define PCI_DEVICE_ID_IBM_CORSA 0x04F0 #define CXLFLASH_SUBS_DEV_ID 0x04F0 @@ -101,4 +101,8 @@ struct asyc_intr_info { #define LINK_RESET 0x02 }; +#ifndef CONFIG_CXL_EEH +#define cxl_perst_reloads_same_image(_a, _b) do { } while (0) +#endif + #endif /* _CXLFLASH_MAIN_H */ diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h old mode 100755 new mode 100644 From 65be2c79acc3aa0f9c0e8d4871f5a451d854465a Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Thu, 13 Aug 2015 21:47:43 -0500 Subject: [PATCH 73/85] cxlflash: Superpipe support Add superpipe supporting infrastructure to device driver for the IBM CXL Flash adapter. This patch allows userspace applications to take advantage of the accelerated I/O features that this adapter provides and bypass the traditional filesystem stack. Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reviewed-by: Michael Neuling Reviewed-by: Wen Xiong Reviewed-by: Brian King Signed-off-by: James Bottomley --- Documentation/ioctl/ioctl-number.txt | 1 + Documentation/powerpc/cxlflash.txt | 257 ++++ drivers/scsi/cxlflash/Makefile | 2 +- drivers/scsi/cxlflash/common.h | 19 + drivers/scsi/cxlflash/lunmgt.c | 263 ++++ drivers/scsi/cxlflash/main.c | 38 +- drivers/scsi/cxlflash/sislite.h | 5 +- drivers/scsi/cxlflash/superpipe.c | 2014 ++++++++++++++++++++++++++ drivers/scsi/cxlflash/superpipe.h | 132 ++ include/uapi/scsi/Kbuild | 1 + include/uapi/scsi/cxlflash_ioctl.h | 140 ++ 11 files changed, 2868 insertions(+), 4 deletions(-) create mode 100644 Documentation/powerpc/cxlflash.txt create mode 100644 drivers/scsi/cxlflash/lunmgt.c create mode 100644 drivers/scsi/cxlflash/superpipe.c create mode 100644 drivers/scsi/cxlflash/superpipe.h create mode 100644 include/uapi/scsi/cxlflash_ioctl.h diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 611c52267d24..9bd118d26a8a 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -314,6 +314,7 @@ Code Seq#(hex) Include File Comments 0xB3 00 linux/mmc/ioctl.h 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h +0xCA 80-8F uapi/scsi/cxlflash_ioctl.h 0xCB 00-1F CBM serial IEC bus in development: 0xCD 01 linux/reiserfs_fs.h diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt new file mode 100644 index 000000000000..f943967f90ce --- /dev/null +++ b/Documentation/powerpc/cxlflash.txt @@ -0,0 +1,257 @@ +Introduction +============ + + The IBM Power architecture provides support for CAPI (Coherent + Accelerator Power Interface), which is available to certain PCIe slots + on Power 8 systems. CAPI can be thought of as a special tunneling + protocol through PCIe that allow PCIe adapters to look like special + purpose co-processors which can read or write an application's + memory and generate page faults. As a result, the host interface to + an adapter running in CAPI mode does not require the data buffers to + be mapped to the device's memory (IOMMU bypass) nor does it require + memory to be pinned. + + On Linux, Coherent Accelerator (CXL) kernel services present CAPI + devices as a PCI device by implementing a virtual PCI host bridge. + This abstraction simplifies the infrastructure and programming + model, allowing for drivers to look similar to other native PCI + device drivers. + + CXL provides a mechanism by which user space applications can + directly talk to a device (network or storage) bypassing the typical + kernel/device driver stack. The CXL Flash Adapter Driver enables a + user space application direct access to Flash storage. + + The CXL Flash Adapter Driver is a kernel module that sits in the + SCSI stack as a low level device driver (below the SCSI disk and + protocol drivers) for the IBM CXL Flash Adapter. This driver is + responsible for the initialization of the adapter, setting up the + special path for user space access, and performing error recovery. It + communicates directly the Flash Accelerator Functional Unit (AFU) + as described in Documentation/powerpc/cxl.txt. + + The cxlflash driver supports two, mutually exclusive, modes of + operation at the device (LUN) level: + + - Any flash device (LUN) can be configured to be accessed as a + regular disk device (i.e.: /dev/sdc). This is the default mode. + + - Any flash device (LUN) can be configured to be accessed from + user space with a special block library. This mode further + specifies the means of accessing the device and provides for + either raw access to the entire LUN (referred to as direct + or physical LUN access) or access to a kernel/AFU-mediated + partition of the LUN (referred to as virtual LUN access). The + segmentation of a disk device into virtual LUNs is assisted + by special translation services provided by the Flash AFU. + +Overview +======== + + The Coherent Accelerator Interface Architecture (CAIA) introduces a + concept of a master context. A master typically has special privileges + granted to it by the kernel or hypervisor allowing it to perform AFU + wide management and control. The master may or may not be involved + directly in each user I/O, but at the minimum is involved in the + initial setup before the user application is allowed to send requests + directly to the AFU. + + The CXL Flash Adapter Driver establishes a master context with the + AFU. It uses memory mapped I/O (MMIO) for this control and setup. The + Adapter Problem Space Memory Map looks like this: + + +-------------------------------+ + | 512 * 64 KB User MMIO | + | (per context) | + | User Accessible | + +-------------------------------+ + | 512 * 128 B per context | + | Provisioning and Control | + | Trusted Process accessible | + +-------------------------------+ + | 64 KB Global | + | Trusted Process accessible | + +-------------------------------+ + + This driver configures itself into the SCSI software stack as an + adapter driver. The driver is the only entity that is considered a + Trusted Process to program the Provisioning and Control and Global + areas in the MMIO Space shown above. The master context driver + discovers all LUNs attached to the CXL Flash adapter and instantiates + scsi block devices (/dev/sdb, /dev/sdc etc.) for each unique LUN + seen from each path. + + Once these scsi block devices are instantiated, an application + written to a specification provided by the block library may get + access to the Flash from user space (without requiring a system call). + + This master context driver also provides a series of ioctls for this + block library to enable this user space access. The driver supports + two modes for accessing the block device. + + The first mode is called a virtual mode. In this mode a single scsi + block device (/dev/sdb) may be carved up into any number of distinct + virtual LUNs. The virtual LUNs may be resized as long as the sum of + the sizes of all the virtual LUNs, along with the meta-data associated + with it does not exceed the physical capacity. + + The second mode is called the physical mode. In this mode a single + block device (/dev/sdb) may be opened directly by the block library + and the entire space for the LUN is available to the application. + + Only the physical mode provides persistence of the data. i.e. The + data written to the block device will survive application exit and + restart and also reboot. The virtual LUNs do not persist (i.e. do + not survive after the application terminates or the system reboots). + + +Block library API +================= + + Applications intending to get access to the CXL Flash from user + space should use the block library, as it abstracts the details of + interfacing directly with the cxlflash driver that are necessary for + performing administrative actions (i.e.: setup, tear down, resize). + The block library can be thought of as a 'user' of services, + implemented as IOCTLs, that are provided by the cxlflash driver + specifically for devices (LUNs) operating in user space access + mode. While it is not a requirement that applications understand + the interface between the block library and the cxlflash driver, + a high-level overview of each supported service (IOCTL) is provided + below. + + The block library can be found on GitHub: + http://www.github.com/mikehollinger/ibmcapikv + + +CXL Flash Driver IOCTLs +======================= + + Users, such as the block library, that wish to interface with a flash + device (LUN) via user space access need to use the services provided + by the cxlflash driver. As these services are implemented as ioctls, + a file descriptor handle must first be obtained in order to establish + the communication channel between a user and the kernel. This file + descriptor is obtained by opening the device special file associated + with the scsi disk device (/dev/sdb) that was created during LUN + discovery. As per the location of the cxlflash driver within the + SCSI protocol stack, this open is actually not seen by the cxlflash + driver. Upon successful open, the user receives a file descriptor + (herein referred to as fd1) that should be used for issuing the + subsequent ioctls listed below. + + The structure definitions for these IOCTLs are available in: + uapi/scsi/cxlflash_ioctl.h + +DK_CXLFLASH_ATTACH +------------------ + + This ioctl obtains, initializes, and starts a context using the CXL + kernel services. These services specify a context id (u16) by which + to uniquely identify the context and its allocated resources. The + services additionally provide a second file descriptor (herein + referred to as fd2) that is used by the block library to initiate + memory mapped I/O (via mmap()) to the CXL flash device and poll for + completion events. This file descriptor is intentionally installed by + this driver and not the CXL kernel services to allow for intermediary + notification and access in the event of a non-user-initiated close(), + such as a killed process. This design point is described in further + detail in the description for the DK_CXLFLASH_DETACH ioctl. + + There are a few important aspects regarding the "tokens" (context id + and fd2) that are provided back to the user: + + - These tokens are only valid for the process under which they + were created. The child of a forked process cannot continue + to use the context id or file descriptor created by its parent. + + - These tokens are only valid for the lifetime of the context and + the process under which they were created. Once either is + destroyed, the tokens are to be considered stale and subsequent + usage will result in errors. + + - When a context is no longer needed, the user shall detach from + the context via the DK_CXLFLASH_DETACH ioctl. + + - A close on fd2 will invalidate the tokens. This operation is not + required by the user. + +DK_CXLFLASH_USER_DIRECT +----------------------- + This ioctl is responsible for transitioning the LUN to direct + (physical) mode access and configuring the AFU for direct access from + user space on a per-context basis. Additionally, the block size and + last logical block address (LBA) are returned to the user. + + As mentioned previously, when operating in user space access mode, + LUNs may be accessed in whole or in part. Only one mode is allowed + at a time and if one mode is active (outstanding references exist), + requests to use the LUN in a different mode are denied. + + The AFU is configured for direct access from user space by adding an + entry to the AFU's resource handle table. The index of the entry is + treated as a resource handle that is returned to the user. The user + is then able to use the handle to reference the LUN during I/O. + +DK_CXLFLASH_RELEASE +------------------- + This ioctl is responsible for releasing a previously obtained + reference to either a physical or virtual LUN. This can be + thought of as the inverse of the DK_CXLFLASH_USER_DIRECT or + DK_CXLFLASH_USER_VIRTUAL ioctls. Upon success, the resource handle + is no longer valid and the entry in the resource handle table is + made available to be used again. + + As part of the release process for virtual LUNs, the virtual LUN + is first resized to 0 to clear out and free the translation tables + associated with the virtual LUN reference. + +DK_CXLFLASH_DETACH +------------------ + This ioctl is responsible for unregistering a context with the + cxlflash driver and release outstanding resources that were + not explicitly released via the DK_CXLFLASH_RELEASE ioctl. Upon + success, all "tokens" which had been provided to the user from the + DK_CXLFLASH_ATTACH onward are no longer valid. + +DK_CXLFLASH_VERIFY +------------------ + This ioctl is used to detect various changes such as the capacity of + the disk changing, the number of LUNs visible changing, etc. In cases + where the changes affect the application (such as a LUN resize), the + cxlflash driver will report the changed state to the application. + + The user calls in when they want to validate that a LUN hasn't been + changed in response to a check condition. As the user is operating out + of band from the kernel, they will see these types of events without + the kernel's knowledge. When encountered, the user's architected + behavior is to call in to this ioctl, indicating what they want to + verify and passing along any appropriate information. For now, only + verifying a LUN change (ie: size different) with sense data is + supported. + +DK_CXLFLASH_RECOVER_AFU +----------------------- + This ioctl is used to drive recovery (if such an action is warranted) + of a specified user context. Any state associated with the user context + is re-established upon successful recovery. + + User contexts are put into an error condition when the device needs to + be reset or is terminating. Users are notified of this error condition + by seeing all 0xF's on an MMIO read. Upon encountering this, the + architected behavior for a user is to call into this ioctl to recover + their context. A user may also call into this ioctl at any time to + check if the device is operating normally. If a failure is returned + from this ioctl, the user is expected to gracefully clean up their + context via release/detach ioctls. Until they do, the context they + hold is not relinquished. The user may also optionally exit the process + at which time the context/resources they held will be freed as part of + the release fop. + +DK_CXLFLASH_MANAGE_LUN +---------------------- + This ioctl is used to switch a LUN from a mode where it is available + for file-system access (legacy), to a mode where it is set aside for + exclusive user space access (superpipe). In case a LUN is visible + across multiple ports and adapters, this ioctl is used to uniquely + identify each LUN by its World Wide Node Name (WWNN). diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile index dc95e203e3af..c14d24c720d6 100644 --- a/drivers/scsi/cxlflash/Makefile +++ b/drivers/scsi/cxlflash/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_CXLFLASH) += cxlflash.o -cxlflash-y += main.o +cxlflash-y += main.o superpipe.o lunmgt.o diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index ffdbc572d180..d3e54e61c7a5 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -107,6 +107,17 @@ struct cxlflash_cfg { struct pci_pool *cxlflash_cmd_pool; struct pci_dev *parent_dev; + atomic_t recovery_threads; + struct mutex ctx_recovery_mutex; + struct mutex ctx_tbl_list_mutex; + struct ctx_info *ctx_tbl[MAX_CONTEXT]; + struct list_head ctx_err_recovery; /* contexts w/ recovery pending */ + struct file_operations cxl_fops; + + atomic_t num_user_contexts; + + struct list_head lluns; /* list of llun_info structs */ + wait_queue_head_t tmf_waitq; bool tmf_active; wait_queue_head_t limbo_waitq; @@ -182,4 +193,12 @@ int cxlflash_afu_reset(struct cxlflash_cfg *); struct afu_cmd *cxlflash_cmd_checkout(struct afu *); void cxlflash_cmd_checkin(struct afu_cmd *); int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8); +void cxlflash_list_init(void); +void cxlflash_term_global_luns(void); +void cxlflash_free_errpage(void); +int cxlflash_ioctl(struct scsi_device *, int, void __user *); +void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *); +int cxlflash_mark_contexts_error(struct cxlflash_cfg *); +void cxlflash_term_local_luns(struct cxlflash_cfg *); + #endif /* ifndef _CXLFLASH_COMMON_H */ diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c new file mode 100644 index 000000000000..66d5bef11ee6 --- /dev/null +++ b/drivers/scsi/cxlflash/lunmgt.c @@ -0,0 +1,263 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +#include +#include + +#include "sislite.h" +#include "common.h" +#include "superpipe.h" + +/** + * create_local() - allocate and initialize a local LUN information structure + * @sdev: SCSI device associated with LUN. + * @wwid: World Wide Node Name for LUN. + * + * Return: Allocated local llun_info structure on success, NULL on failure + */ +static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid) +{ + struct llun_info *lli = NULL; + + lli = kzalloc(sizeof(*lli), GFP_KERNEL); + if (unlikely(!lli)) { + pr_err("%s: could not allocate lli\n", __func__); + goto out; + } + + lli->sdev = sdev; + lli->newly_created = true; + lli->host_no = sdev->host->host_no; + + memcpy(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN); +out: + return lli; +} + +/** + * create_global() - allocate and initialize a global LUN information structure + * @sdev: SCSI device associated with LUN. + * @wwid: World Wide Node Name for LUN. + * + * Return: Allocated global glun_info structure on success, NULL on failure + */ +static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid) +{ + struct glun_info *gli = NULL; + + gli = kzalloc(sizeof(*gli), GFP_KERNEL); + if (unlikely(!gli)) { + pr_err("%s: could not allocate gli\n", __func__); + goto out; + } + + mutex_init(&gli->mutex); + memcpy(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN); +out: + return gli; +} + +/** + * refresh_local() - find and update local LUN information structure by WWID + * @cfg: Internal structure associated with the host. + * @wwid: WWID associated with LUN. + * + * When the LUN is found, mark it by updating it's newly_created field. + * + * Return: Found local lun_info structure on success, NULL on failure + * If a LUN with the WWID is found in the list, refresh it's state. + */ +static struct llun_info *refresh_local(struct cxlflash_cfg *cfg, u8 *wwid) +{ + struct llun_info *lli, *temp; + + list_for_each_entry_safe(lli, temp, &cfg->lluns, list) + if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN)) { + lli->newly_created = false; + return lli; + } + + return NULL; +} + +/** + * lookup_global() - find a global LUN information structure by WWID + * @wwid: WWID associated with LUN. + * + * Return: Found global lun_info structure on success, NULL on failure + */ +static struct glun_info *lookup_global(u8 *wwid) +{ + struct glun_info *gli, *temp; + + list_for_each_entry_safe(gli, temp, &global.gluns, list) + if (!memcmp(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN)) + return gli; + + return NULL; +} + +/** + * find_and_create_lun() - find or create a local LUN information structure + * @sdev: SCSI device associated with LUN. + * @wwid: WWID associated with LUN. + * + * The LUN is kept both in a local list (per adapter) and in a global list + * (across all adapters). Certain attributes of the LUN are local to the + * adapter (such as index, port selection mask etc.). + * The block allocation map is shared across all adapters (i.e. associated + * wih the global list). Since different attributes are associated with + * the per adapter and global entries, allocate two separate structures for each + * LUN (one local, one global). + * + * Keep a pointer back from the local to the global entry. + * + * Return: Found/Allocated local lun_info structure on success, NULL on failure + */ +static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid) +{ + struct llun_info *lli = NULL; + struct glun_info *gli = NULL; + struct Scsi_Host *shost = sdev->host; + struct cxlflash_cfg *cfg = shost_priv(shost); + + mutex_lock(&global.mutex); + if (unlikely(!wwid)) + goto out; + + lli = refresh_local(cfg, wwid); + if (lli) + goto out; + + lli = create_local(sdev, wwid); + if (unlikely(!lli)) + goto out; + + gli = lookup_global(wwid); + if (gli) { + lli->parent = gli; + list_add(&lli->list, &cfg->lluns); + goto out; + } + + gli = create_global(sdev, wwid); + if (unlikely(!gli)) { + kfree(lli); + lli = NULL; + goto out; + } + + lli->parent = gli; + list_add(&lli->list, &cfg->lluns); + + list_add(&gli->list, &global.gluns); + +out: + mutex_unlock(&global.mutex); + pr_debug("%s: returning %p\n", __func__, lli); + return lli; +} + +/** + * cxlflash_term_local_luns() - Delete all entries from local LUN list, free. + * @cfg: Internal structure associated with the host. + */ +void cxlflash_term_local_luns(struct cxlflash_cfg *cfg) +{ + struct llun_info *lli, *temp; + + mutex_lock(&global.mutex); + list_for_each_entry_safe(lli, temp, &cfg->lluns, list) { + list_del(&lli->list); + kfree(lli); + } + mutex_unlock(&global.mutex); +} + +/** + * cxlflash_list_init() - initializes the global LUN list + */ +void cxlflash_list_init(void) +{ + INIT_LIST_HEAD(&global.gluns); + mutex_init(&global.mutex); + global.err_page = NULL; +} + +/** + * cxlflash_term_global_luns() - frees resources associated with global LUN list + */ +void cxlflash_term_global_luns(void) +{ + struct glun_info *gli, *temp; + + mutex_lock(&global.mutex); + list_for_each_entry_safe(gli, temp, &global.gluns, list) { + list_del(&gli->list); + kfree(gli); + } + mutex_unlock(&global.mutex); +} + +/** + * cxlflash_manage_lun() - handles LUN management activities + * @sdev: SCSI device associated with LUN. + * @manage: Manage ioctl data structure. + * + * This routine is used to notify the driver about a LUN's WWID and associate + * SCSI devices (sdev) with a global LUN instance. Additionally it serves to + * change a LUN's operating mode: legacy or superpipe. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_manage_lun(struct scsi_device *sdev, + struct dk_cxlflash_manage_lun *manage) +{ + int rc = 0; + struct llun_info *lli = NULL; + u64 flags = manage->hdr.flags; + u32 chan = sdev->channel; + + lli = find_and_create_lun(sdev, manage->wwid); + pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n", + __func__, get_unaligned_le64(&manage->wwid[0]), + get_unaligned_le64(&manage->wwid[8]), + manage->hdr.flags, lli); + if (unlikely(!lli)) { + rc = -ENOMEM; + goto out; + } + + if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) { + if (lli->newly_created) + lli->port_sel = CHAN2PORT(chan); + else + lli->port_sel = BOTH_PORTS; + /* Store off lun in unpacked, AFU-friendly format */ + lli->lun_id[chan] = lun_to_lunid(sdev->lun); + sdev->hostdata = lli; + } else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) { + if (lli->parent->mode != MODE_NONE) + rc = -EBUSY; + else + sdev->hostdata = NULL; + } + +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 3ae8dca236ef..02d464f41b7f 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -23,6 +23,7 @@ #include #include +#include #include "main.h" #include "sislite.h" @@ -519,7 +520,7 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) case STATE_NORMAL: cfg->state = STATE_LIMBO; scsi_block_requests(cfg->host); - + cxlflash_mark_contexts_error(cfg); rcr = cxlflash_afu_reset(cfg); if (rcr) { rc = FAILED; @@ -662,6 +663,21 @@ static ssize_t cxlflash_store_lun_mode(struct device *dev, return count; } +/** + * cxlflash_show_ioctl_version() - presents the current ioctl version of the host + * @dev: Generic device associated with the host. + * @attr: Device attribute representing the ioctl version. + * @buf: Buffer of length PAGE_SIZE to report back the ioctl version. + * + * Return: The size of the ASCII string returned in @buf. + */ +static ssize_t cxlflash_show_ioctl_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0); +} + /** * cxlflash_show_dev_mode() - presents the current mode of the device * @dev: Generic device associated with the device. @@ -700,11 +716,13 @@ static DEVICE_ATTR(port0, S_IRUGO, cxlflash_show_port_status, NULL); static DEVICE_ATTR(port1, S_IRUGO, cxlflash_show_port_status, NULL); static DEVICE_ATTR(lun_mode, S_IRUGO | S_IWUSR, cxlflash_show_lun_mode, cxlflash_store_lun_mode); +static DEVICE_ATTR(ioctl_version, S_IRUGO, cxlflash_show_ioctl_version, NULL); static struct device_attribute *cxlflash_host_attrs[] = { &dev_attr_port0, &dev_attr_port1, &dev_attr_lun_mode, + &dev_attr_ioctl_version, NULL }; @@ -725,6 +743,7 @@ static struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = CXLFLASH_ADAPTER_NAME, .info = cxlflash_driver_info, + .ioctl = cxlflash_ioctl, .proc_name = CXLFLASH_NAME, .queuecommand = cxlflash_queuecommand, .eh_device_reset_handler = cxlflash_eh_device_reset_handler, @@ -872,9 +891,11 @@ static void cxlflash_remove(struct pci_dev *pdev) spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags); cfg->state = STATE_FAILTERM; + cxlflash_stop_term_user_contexts(cfg); switch (cfg->init_state) { case INIT_STATE_SCSI: + cxlflash_term_local_luns(cfg); scsi_remove_host(cfg->host); scsi_host_put(cfg->host); /* Fall through */ @@ -2274,6 +2295,10 @@ static int cxlflash_probe(struct pci_dev *pdev, INIT_WORK(&cfg->work_q, cxlflash_worker_thread); cfg->lr_state = LINK_RESET_INVALID; cfg->lr_port = -1; + mutex_init(&cfg->ctx_tbl_list_mutex); + mutex_init(&cfg->ctx_recovery_mutex); + INIT_LIST_HEAD(&cfg->ctx_err_recovery); + INIT_LIST_HEAD(&cfg->lluns); pci_set_drvdata(pdev, cfg); @@ -2335,6 +2360,7 @@ out_remove: static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { + int rc = 0; struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); struct device *dev = &cfg->dev->dev; @@ -2346,7 +2372,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, /* Turn off legacy I/O */ scsi_block_requests(cfg->host); - + rc = cxlflash_mark_contexts_error(cfg); + if (unlikely(rc)) + dev_err(dev, "%s: Failed to mark user contexts!(%d)\n", + __func__, rc); term_mc(cfg, UNDO_START); stop_afu(cfg); @@ -2431,6 +2460,8 @@ static int __init init_cxlflash(void) pr_info("%s: IBM Power CXL Flash Adapter: %s\n", __func__, CXLFLASH_DRIVER_DATE); + cxlflash_list_init(); + return pci_register_driver(&cxlflash_driver); } @@ -2439,6 +2470,9 @@ static int __init init_cxlflash(void) */ static void __exit exit_cxlflash(void) { + cxlflash_term_global_luns(); + cxlflash_free_errpage(); + pci_unregister_driver(&cxlflash_driver); } diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h index bf5d39978630..66b889151a4c 100644 --- a/drivers/scsi/cxlflash/sislite.h +++ b/drivers/scsi/cxlflash/sislite.h @@ -409,7 +409,10 @@ struct sisl_lxt_entry { }; -/* Per the SISlite spec, RHT entries are to be 16-byte aligned */ +/* + * RHT - Resource Handle Table + * Per the SISlite spec, RHT entries are to be 16-byte aligned + */ struct sisl_rht_entry { struct sisl_lxt_entry *lxt_start; u32 lxt_cnt; diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c new file mode 100644 index 000000000000..3c8bce8bbb0b --- /dev/null +++ b/drivers/scsi/cxlflash/superpipe.c @@ -0,0 +1,2014 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sislite.h" +#include "common.h" +#include "superpipe.h" + +struct cxlflash_global global; + +/** + * marshal_det_to_rele() - translate detach to release structure + * @detach: Destination structure for the translate/copy. + * @rele: Source structure from which to translate/copy. + */ +static void marshal_det_to_rele(struct dk_cxlflash_detach *detach, + struct dk_cxlflash_release *release) +{ + release->hdr = detach->hdr; + release->context_id = detach->context_id; +} + +/** + * cxlflash_free_errpage() - frees resources associated with global error page + */ +void cxlflash_free_errpage(void) +{ + + mutex_lock(&global.mutex); + if (global.err_page) { + __free_page(global.err_page); + global.err_page = NULL; + } + mutex_unlock(&global.mutex); +} + +/** + * cxlflash_stop_term_user_contexts() - stops/terminates known user contexts + * @cfg: Internal structure associated with the host. + * + * When the host needs to go down, all users must be quiesced and their + * memory freed. This is accomplished by putting the contexts in error + * state which will notify the user and let them 'drive' the tear-down. + * Meanwhile, this routine camps until all user contexts have been removed. + */ +void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg) +{ + struct device *dev = &cfg->dev->dev; + int i, found; + + cxlflash_mark_contexts_error(cfg); + + while (true) { + found = false; + + for (i = 0; i < MAX_CONTEXT; i++) + if (cfg->ctx_tbl[i]) { + found = true; + break; + } + + if (!found && list_empty(&cfg->ctx_err_recovery)) + return; + + dev_dbg(dev, "%s: Wait for user contexts to quiesce...\n", + __func__); + wake_up_all(&cfg->limbo_waitq); + ssleep(1); + } +} + +/** + * find_error_context() - locates a context by cookie on the error recovery list + * @cfg: Internal structure associated with the host. + * @rctxid: Desired context by id. + * @file: Desired context by file. + * + * Return: Found context on success, NULL on failure + */ +static struct ctx_info *find_error_context(struct cxlflash_cfg *cfg, u64 rctxid, + struct file *file) +{ + struct ctx_info *ctxi; + + list_for_each_entry(ctxi, &cfg->ctx_err_recovery, list) + if ((ctxi->ctxid == rctxid) || (ctxi->file == file)) + return ctxi; + + return NULL; +} + +/** + * get_context() - obtains a validated and locked context reference + * @cfg: Internal structure associated with the host. + * @rctxid: Desired context (raw, un-decoded format). + * @arg: LUN information or file associated with request. + * @ctx_ctrl: Control information to 'steer' desired lookup. + * + * NOTE: despite the name pid, in linux, current->pid actually refers + * to the lightweight process id (tid) and can change if the process is + * multi threaded. The tgid remains constant for the process and only changes + * when the process of fork. For all intents and purposes, think of tgid + * as a pid in the traditional sense. + * + * Return: Validated context on success, NULL on failure + */ +struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid, + void *arg, enum ctx_ctrl ctx_ctrl) +{ + struct device *dev = &cfg->dev->dev; + struct ctx_info *ctxi = NULL; + struct lun_access *lun_access = NULL; + struct file *file = NULL; + struct llun_info *lli = arg; + u64 ctxid = DECODE_CTXID(rctxid); + int rc; + pid_t pid = current->tgid, ctxpid = 0; + + if (ctx_ctrl & CTX_CTRL_FILE) { + lli = NULL; + file = (struct file *)arg; + } + + if (ctx_ctrl & CTX_CTRL_CLONE) + pid = current->parent->tgid; + + if (likely(ctxid < MAX_CONTEXT)) { + while (true) { + rc = mutex_lock_interruptible(&cfg->ctx_tbl_list_mutex); + if (rc) + goto out; + + ctxi = cfg->ctx_tbl[ctxid]; + if (ctxi) + if ((file && (ctxi->file != file)) || + (!file && (ctxi->ctxid != rctxid))) + ctxi = NULL; + + if ((ctx_ctrl & CTX_CTRL_ERR) || + (!ctxi && (ctx_ctrl & CTX_CTRL_ERR_FALLBACK))) + ctxi = find_error_context(cfg, rctxid, file); + if (!ctxi) { + mutex_unlock(&cfg->ctx_tbl_list_mutex); + goto out; + } + + /* + * Need to acquire ownership of the context while still + * under the table/list lock to serialize with a remove + * thread. Use the 'try' to avoid stalling the + * table/list lock for a single context. + * + * Note that the lock order is: + * + * cfg->ctx_tbl_list_mutex -> ctxi->mutex + * + * Therefore release ctx_tbl_list_mutex before retrying. + */ + rc = mutex_trylock(&ctxi->mutex); + mutex_unlock(&cfg->ctx_tbl_list_mutex); + if (rc) + break; /* got the context's lock! */ + } + + if (ctxi->unavail) + goto denied; + + ctxpid = ctxi->pid; + if (likely(!(ctx_ctrl & CTX_CTRL_NOPID))) + if (pid != ctxpid) + goto denied; + + if (lli) { + list_for_each_entry(lun_access, &ctxi->luns, list) + if (lun_access->lli == lli) + goto out; + goto denied; + } + } + +out: + dev_dbg(dev, "%s: rctxid=%016llX ctxinfo=%p ctxpid=%u pid=%u " + "ctx_ctrl=%u\n", __func__, rctxid, ctxi, ctxpid, pid, + ctx_ctrl); + + return ctxi; + +denied: + mutex_unlock(&ctxi->mutex); + ctxi = NULL; + goto out; +} + +/** + * put_context() - release a context that was retrieved from get_context() + * @ctxi: Context to release. + * + * For now, releasing the context equates to unlocking it's mutex. + */ +void put_context(struct ctx_info *ctxi) +{ + mutex_unlock(&ctxi->mutex); +} + +/** + * afu_attach() - attach a context to the AFU + * @cfg: Internal structure associated with the host. + * @ctxi: Context to attach. + * + * Upon setting the context capabilities, they must be confirmed with + * a read back operation as the context might have been closed since + * the mailbox was unlocked. When this occurs, registration is failed. + * + * Return: 0 on success, -errno on failure + */ +static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) +{ + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + struct sisl_ctrl_map *ctrl_map = ctxi->ctrl_map; + int rc = 0; + u64 val; + + /* Unlock cap and restrict user to read/write cmds in translated mode */ + readq_be(&ctrl_map->mbox_r); + val = (SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD); + writeq_be(val, &ctrl_map->ctx_cap); + val = readq_be(&ctrl_map->ctx_cap); + if (val != (SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD)) { + dev_err(dev, "%s: ctx may be closed val=%016llX\n", + __func__, val); + rc = -EAGAIN; + goto out; + } + + /* Set up MMIO registers pointing to the RHT */ + writeq_be((u64)ctxi->rht_start, &ctrl_map->rht_start); + val = SISL_RHT_CNT_ID((u64)MAX_RHT_PER_CONTEXT, (u64)(afu->ctx_hndl)); + writeq_be(val, &ctrl_map->rht_cnt_id); +out: + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * read_cap16() - issues a SCSI READ_CAP16 command + * @sdev: SCSI device associated with LUN. + * @lli: LUN destined for capacity request. + * + * Return: 0 on success, -errno on failure + */ +static int read_cap16(struct scsi_device *sdev, struct llun_info *lli) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct glun_info *gli = lli->parent; + u8 *cmd_buf = NULL; + u8 *scsi_cmd = NULL; + u8 *sense_buf = NULL; + int rc = 0; + int result = 0; + int retry_cnt = 0; + u32 tout = (MC_DISCOVERY_TIMEOUT * HZ); + +retry: + cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL); + scsi_cmd = kzalloc(MAX_COMMAND_SIZE, GFP_KERNEL); + sense_buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (unlikely(!cmd_buf || !scsi_cmd || !sense_buf)) { + rc = -ENOMEM; + goto out; + } + + scsi_cmd[0] = SERVICE_ACTION_IN_16; /* read cap(16) */ + scsi_cmd[1] = SAI_READ_CAPACITY_16; /* service action */ + put_unaligned_be32(CMD_BUFSIZE, &scsi_cmd[10]); + + dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__, + retry_cnt ? "re" : "", scsi_cmd[0]); + + result = scsi_execute(sdev, scsi_cmd, DMA_FROM_DEVICE, cmd_buf, + CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL); + + if (driver_byte(result) == DRIVER_SENSE) { + result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ + if (result & SAM_STAT_CHECK_CONDITION) { + struct scsi_sense_hdr sshdr; + + scsi_normalize_sense(sense_buf, SCSI_SENSE_BUFFERSIZE, + &sshdr); + switch (sshdr.sense_key) { + case NO_SENSE: + case RECOVERED_ERROR: + /* fall through */ + case NOT_READY: + result &= ~SAM_STAT_CHECK_CONDITION; + break; + case UNIT_ATTENTION: + switch (sshdr.asc) { + case 0x29: /* Power on Reset or Device Reset */ + /* fall through */ + case 0x2A: /* Device capacity changed */ + case 0x3F: /* Report LUNs changed */ + /* Retry the command once more */ + if (retry_cnt++ < 1) { + kfree(cmd_buf); + kfree(scsi_cmd); + kfree(sense_buf); + goto retry; + } + } + break; + default: + break; + } + } + } + + if (result) { + dev_err(dev, "%s: command failed, result=0x%x\n", + __func__, result); + rc = -EIO; + goto out; + } + + /* + * Read cap was successful, grab values from the buffer; + * note that we don't need to worry about unaligned access + * as the buffer is allocated on an aligned boundary. + */ + mutex_lock(&gli->mutex); + gli->max_lba = be64_to_cpu(*((u64 *)&cmd_buf[0])); + gli->blk_len = be32_to_cpu(*((u32 *)&cmd_buf[8])); + mutex_unlock(&gli->mutex); + +out: + kfree(cmd_buf); + kfree(scsi_cmd); + kfree(sense_buf); + + dev_dbg(dev, "%s: maxlba=%lld blklen=%d rc=%d\n", + __func__, gli->max_lba, gli->blk_len, rc); + return rc; +} + +/** + * get_rhte() - obtains validated resource handle table entry reference + * @ctxi: Context owning the resource handle. + * @rhndl: Resource handle associated with entry. + * @lli: LUN associated with request. + * + * Return: Validated RHTE on success, NULL on failure + */ +struct sisl_rht_entry *get_rhte(struct ctx_info *ctxi, res_hndl_t rhndl, + struct llun_info *lli) +{ + struct sisl_rht_entry *rhte = NULL; + + if (unlikely(!ctxi->rht_start)) { + pr_debug("%s: Context does not have allocated RHT!\n", + __func__); + goto out; + } + + if (unlikely(rhndl >= MAX_RHT_PER_CONTEXT)) { + pr_debug("%s: Bad resource handle! (%d)\n", __func__, rhndl); + goto out; + } + + if (unlikely(ctxi->rht_lun[rhndl] != lli)) { + pr_debug("%s: Bad resource handle LUN! (%d)\n", + __func__, rhndl); + goto out; + } + + rhte = &ctxi->rht_start[rhndl]; + if (unlikely(rhte->nmask == 0)) { + pr_debug("%s: Unopened resource handle! (%d)\n", + __func__, rhndl); + rhte = NULL; + goto out; + } + +out: + return rhte; +} + +/** + * rhte_checkout() - obtains free/empty resource handle table entry + * @ctxi: Context owning the resource handle. + * @lli: LUN associated with request. + * + * Return: Free RHTE on success, NULL on failure + */ +struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi, + struct llun_info *lli) +{ + struct sisl_rht_entry *rhte = NULL; + int i; + + /* Find a free RHT entry */ + for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) + if (ctxi->rht_start[i].nmask == 0) { + rhte = &ctxi->rht_start[i]; + ctxi->rht_out++; + break; + } + + if (likely(rhte)) + ctxi->rht_lun[i] = lli; + + pr_debug("%s: returning rhte=%p (%d)\n", __func__, rhte, i); + return rhte; +} + +/** + * rhte_checkin() - releases a resource handle table entry + * @ctxi: Context owning the resource handle. + * @rhte: RHTE to release. + */ +void rhte_checkin(struct ctx_info *ctxi, + struct sisl_rht_entry *rhte) +{ + u32 rsrc_handle = rhte - ctxi->rht_start; + + rhte->nmask = 0; + rhte->fp = 0; + ctxi->rht_out--; + ctxi->rht_lun[rsrc_handle] = NULL; +} + +/** + * rhte_format1() - populates a RHTE for format 1 + * @rhte: RHTE to populate. + * @lun_id: LUN ID of LUN associated with RHTE. + * @perm: Desired permissions for RHTE. + * @port_sel: Port selection mask + */ +static void rht_format1(struct sisl_rht_entry *rhte, u64 lun_id, u32 perm, + u32 port_sel) +{ + /* + * Populate the Format 1 RHT entry for direct access (physical + * LUN) using the synchronization sequence defined in the + * SISLite specification. + */ + struct sisl_rht_entry_f1 dummy = { 0 }; + struct sisl_rht_entry_f1 *rhte_f1 = (struct sisl_rht_entry_f1 *)rhte; + + memset(rhte_f1, 0, sizeof(*rhte_f1)); + rhte_f1->fp = SISL_RHT_FP(1U, 0); + dma_wmb(); /* Make setting of format bit visible */ + + rhte_f1->lun_id = lun_id; + dma_wmb(); /* Make setting of LUN id visible */ + + /* + * Use a dummy RHT Format 1 entry to build the second dword + * of the entry that must be populated in a single write when + * enabled (valid bit set to TRUE). + */ + dummy.valid = 0x80; + dummy.fp = SISL_RHT_FP(1U, perm); + dummy.port_sel = port_sel; + rhte_f1->dw = dummy.dw; + + dma_wmb(); /* Make remaining RHT entry fields visible */ +} + +/** + * cxlflash_lun_attach() - attaches a user to a LUN and manages the LUN's mode + * @gli: LUN to attach. + * @mode: Desired mode of the LUN. + * @locked: Mutex status on current thread. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_lun_attach(struct glun_info *gli, enum lun_mode mode, bool locked) +{ + int rc = 0; + + if (!locked) + mutex_lock(&gli->mutex); + + if (gli->mode == MODE_NONE) + gli->mode = mode; + else if (gli->mode != mode) { + pr_debug("%s: LUN operating in mode %d, requested mode %d\n", + __func__, gli->mode, mode); + rc = -EINVAL; + goto out; + } + + gli->users++; + WARN_ON(gli->users <= 0); +out: + pr_debug("%s: Returning rc=%d gli->mode=%u gli->users=%u\n", + __func__, rc, gli->mode, gli->users); + if (!locked) + mutex_unlock(&gli->mutex); + return rc; +} + +/** + * cxlflash_lun_detach() - detaches a user from a LUN and resets the LUN's mode + * @gli: LUN to detach. + */ +void cxlflash_lun_detach(struct glun_info *gli) +{ + mutex_lock(&gli->mutex); + WARN_ON(gli->mode == MODE_NONE); + if (--gli->users == 0) + gli->mode = MODE_NONE; + pr_debug("%s: gli->users=%u\n", __func__, gli->users); + WARN_ON(gli->users < 0); + mutex_unlock(&gli->mutex); +} + +/** + * _cxlflash_disk_release() - releases the specified resource entry + * @sdev: SCSI device associated with LUN. + * @ctxi: Context owning resources. + * @release: Release ioctl data structure. + * + * Note that the AFU sync should _not_ be performed when the context is sitting + * on the error recovery list. A context on the error recovery list is not known + * to the AFU due to reset. When the context is recovered, it will be reattached + * and made known again to the AFU. + * + * Return: 0 on success, -errno on failure + */ +int _cxlflash_disk_release(struct scsi_device *sdev, + struct ctx_info *ctxi, + struct dk_cxlflash_release *release) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct afu *afu = cfg->afu; + bool put_ctx = false; + + res_hndl_t rhndl = release->rsrc_handle; + + int rc = 0; + u64 ctxid = DECODE_CTXID(release->context_id), + rctxid = release->context_id; + + struct sisl_rht_entry *rhte; + struct sisl_rht_entry_f1 *rhte_f1; + + dev_dbg(dev, "%s: ctxid=%llu rhndl=0x%llx gli->mode=%u gli->users=%u\n", + __func__, ctxid, release->rsrc_handle, gli->mode, gli->users); + + if (!ctxi) { + ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%llu)\n", + __func__, ctxid); + rc = -EINVAL; + goto out; + } + + put_ctx = true; + } + + rhte = get_rhte(ctxi, rhndl, lli); + if (unlikely(!rhte)) { + dev_dbg(dev, "%s: Bad resource handle! (%d)\n", + __func__, rhndl); + rc = -EINVAL; + goto out; + } + + switch (gli->mode) { + case MODE_PHYSICAL: + /* + * Clear the Format 1 RHT entry for direct access + * (physical LUN) using the synchronization sequence + * defined in the SISLite specification. + */ + rhte_f1 = (struct sisl_rht_entry_f1 *)rhte; + + rhte_f1->valid = 0; + dma_wmb(); /* Make revocation of RHT entry visible */ + + rhte_f1->lun_id = 0; + dma_wmb(); /* Make clearing of LUN id visible */ + + rhte_f1->dw = 0; + dma_wmb(); /* Make RHT entry bottom-half clearing visible */ + + if (!ctxi->err_recovery_active) + cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC); + break; + default: + WARN(1, "Unsupported LUN mode!"); + goto out; + } + + rhte_checkin(ctxi, rhte); + cxlflash_lun_detach(gli); + +out: + if (put_ctx) + put_context(ctxi); + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); + return rc; +} + +int cxlflash_disk_release(struct scsi_device *sdev, + struct dk_cxlflash_release *release) +{ + return _cxlflash_disk_release(sdev, NULL, release); +} + +/** + * destroy_context() - releases a context + * @cfg: Internal structure associated with the host. + * @ctxi: Context to release. + * + * Note that the rht_lun member of the context was cut from a single + * allocation when the context was created and therefore does not need + * to be explicitly freed. Also note that we conditionally check for the + * existence of the context control map before clearing the RHT registers + * and context capabilities because it is possible to destroy a context + * while the context is in the error state (previous mapping was removed + * [so we don't have to worry about clearing] and context is waiting for + * a new mapping). + */ +static void destroy_context(struct cxlflash_cfg *cfg, + struct ctx_info *ctxi) +{ + struct afu *afu = cfg->afu; + + WARN_ON(!list_empty(&ctxi->luns)); + + /* Clear RHT registers and drop all capabilities for this context */ + if (afu->afu_map && ctxi->ctrl_map) { + writeq_be(0, &ctxi->ctrl_map->rht_start); + writeq_be(0, &ctxi->ctrl_map->rht_cnt_id); + writeq_be(0, &ctxi->ctrl_map->ctx_cap); + } + + /* Free memory associated with context */ + free_page((ulong)ctxi->rht_start); + kfree(ctxi->rht_lun); + kfree(ctxi); + atomic_dec_if_positive(&cfg->num_user_contexts); +} + +/** + * create_context() - allocates and initializes a context + * @cfg: Internal structure associated with the host. + * @ctx: Previously obtained CXL context reference. + * @ctxid: Previously obtained process element associated with CXL context. + * @adap_fd: Previously obtained adapter fd associated with CXL context. + * @file: Previously obtained file associated with CXL context. + * @perms: User-specified permissions. + * + * The context's mutex is locked when an allocated context is returned. + * + * Return: Allocated context on success, NULL on failure + */ +static struct ctx_info *create_context(struct cxlflash_cfg *cfg, + struct cxl_context *ctx, int ctxid, + int adap_fd, struct file *file, + u32 perms) +{ + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + struct ctx_info *ctxi = NULL; + struct llun_info **lli = NULL; + struct sisl_rht_entry *rhte; + + ctxi = kzalloc(sizeof(*ctxi), GFP_KERNEL); + lli = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*lli)), GFP_KERNEL); + if (unlikely(!ctxi || !lli)) { + dev_err(dev, "%s: Unable to allocate context!\n", __func__); + goto err; + } + + rhte = (struct sisl_rht_entry *)get_zeroed_page(GFP_KERNEL); + if (unlikely(!rhte)) { + dev_err(dev, "%s: Unable to allocate RHT!\n", __func__); + goto err; + } + + ctxi->rht_lun = lli; + ctxi->rht_start = rhte; + ctxi->rht_perms = perms; + + ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl; + ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); + ctxi->lfd = adap_fd; + ctxi->pid = current->tgid; /* tgid = pid */ + ctxi->ctx = ctx; + ctxi->file = file; + mutex_init(&ctxi->mutex); + INIT_LIST_HEAD(&ctxi->luns); + INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */ + + atomic_inc(&cfg->num_user_contexts); + mutex_lock(&ctxi->mutex); +out: + return ctxi; + +err: + kfree(lli); + kfree(ctxi); + ctxi = NULL; + goto out; +} + +/** + * _cxlflash_disk_detach() - detaches a LUN from a context + * @sdev: SCSI device associated with LUN. + * @ctxi: Context owning resources. + * @detach: Detach ioctl data structure. + * + * As part of the detach, all per-context resources associated with the LUN + * are cleaned up. When detaching the last LUN for a context, the context + * itself is cleaned up and released. + * + * Return: 0 on success, -errno on failure + */ +static int _cxlflash_disk_detach(struct scsi_device *sdev, + struct ctx_info *ctxi, + struct dk_cxlflash_detach *detach) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct lun_access *lun_access, *t; + struct dk_cxlflash_release rel; + bool put_ctx = false; + + int i; + int rc = 0; + int lfd; + u64 ctxid = DECODE_CTXID(detach->context_id), + rctxid = detach->context_id; + + dev_dbg(dev, "%s: ctxid=%llu\n", __func__, ctxid); + + if (!ctxi) { + ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%llu)\n", + __func__, ctxid); + rc = -EINVAL; + goto out; + } + + put_ctx = true; + } + + /* Cleanup outstanding resources tied to this LUN */ + if (ctxi->rht_out) { + marshal_det_to_rele(detach, &rel); + for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) { + if (ctxi->rht_lun[i] == lli) { + rel.rsrc_handle = i; + _cxlflash_disk_release(sdev, ctxi, &rel); + } + + /* No need to loop further if we're done */ + if (ctxi->rht_out == 0) + break; + } + } + + /* Take our LUN out of context, free the node */ + list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) + if (lun_access->lli == lli) { + list_del(&lun_access->list); + kfree(lun_access); + lun_access = NULL; + break; + } + + /* Tear down context following last LUN cleanup */ + if (list_empty(&ctxi->luns)) { + ctxi->unavail = true; + mutex_unlock(&ctxi->mutex); + mutex_lock(&cfg->ctx_tbl_list_mutex); + mutex_lock(&ctxi->mutex); + + /* Might not have been in error list so conditionally remove */ + if (!list_empty(&ctxi->list)) + list_del(&ctxi->list); + cfg->ctx_tbl[ctxid] = NULL; + mutex_unlock(&cfg->ctx_tbl_list_mutex); + mutex_unlock(&ctxi->mutex); + + lfd = ctxi->lfd; + destroy_context(cfg, ctxi); + ctxi = NULL; + put_ctx = false; + + /* + * As a last step, clean up external resources when not + * already on an external cleanup thread, i.e.: close(adap_fd). + * + * NOTE: this will free up the context from the CXL services, + * allowing it to dole out the same context_id on a future + * (or even currently in-flight) disk_attach operation. + */ + if (lfd != -1) + sys_close(lfd); + } + +out: + if (put_ctx) + put_context(ctxi); + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); + return rc; +} + +static int cxlflash_disk_detach(struct scsi_device *sdev, + struct dk_cxlflash_detach *detach) +{ + return _cxlflash_disk_detach(sdev, NULL, detach); +} + +/** + * cxlflash_cxl_release() - release handler for adapter file descriptor + * @inode: File-system inode associated with fd. + * @file: File installed with adapter file descriptor. + * + * This routine is the release handler for the fops registered with + * the CXL services on an initial attach for a context. It is called + * when a close is performed on the adapter file descriptor returned + * to the user. Programmatically, the user is not required to perform + * the close, as it is handled internally via the detach ioctl when + * a context is being removed. Note that nothing prevents the user + * from performing a close, but the user should be aware that doing + * so is considered catastrophic and subsequent usage of the superpipe + * API with previously saved off tokens will fail. + * + * When initiated from an external close (either by the user or via + * a process tear down), the routine derives the context reference + * and calls detach for each LUN associated with the context. The + * final detach operation will cause the context itself to be freed. + * Note that the saved off lfd is reset prior to calling detach to + * signify that the final detach should not perform a close. + * + * When initiated from a detach operation as part of the tear down + * of a context, the context is first completely freed and then the + * close is performed. This routine will fail to derive the context + * reference (due to the context having already been freed) and then + * call into the CXL release entry point. + * + * Thus, with exception to when the CXL process element (context id) + * lookup fails (a case that should theoretically never occur), every + * call into this routine results in a complete freeing of a context. + * + * As part of the detach, all per-context resources associated with the LUN + * are cleaned up. When detaching the last LUN for a context, the context + * itself is cleaned up and released. + * + * Return: 0 on success + */ +static int cxlflash_cxl_release(struct inode *inode, struct file *file) +{ + struct cxl_context *ctx = cxl_fops_get_context(file); + struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg, + cxl_fops); + struct device *dev = &cfg->dev->dev; + struct ctx_info *ctxi = NULL; + struct dk_cxlflash_detach detach = { { 0 }, 0 }; + struct lun_access *lun_access, *t; + enum ctx_ctrl ctrl = CTX_CTRL_ERR_FALLBACK | CTX_CTRL_FILE; + int ctxid; + + ctxid = cxl_process_element(ctx); + if (unlikely(ctxid < 0)) { + dev_err(dev, "%s: Context %p was closed! (%d)\n", + __func__, ctx, ctxid); + goto out; + } + + ctxi = get_context(cfg, ctxid, file, ctrl); + if (unlikely(!ctxi)) { + ctxi = get_context(cfg, ctxid, file, ctrl | CTX_CTRL_CLONE); + if (!ctxi) { + dev_dbg(dev, "%s: Context %d already free!\n", + __func__, ctxid); + goto out_release; + } + + dev_dbg(dev, "%s: Another process owns context %d!\n", + __func__, ctxid); + put_context(ctxi); + goto out; + } + + dev_dbg(dev, "%s: close(%d) for context %d\n", + __func__, ctxi->lfd, ctxid); + + /* Reset the file descriptor to indicate we're on a close() thread */ + ctxi->lfd = -1; + detach.context_id = ctxi->ctxid; + list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) + _cxlflash_disk_detach(lun_access->sdev, ctxi, &detach); +out_release: + cxl_fd_release(inode, file); +out: + dev_dbg(dev, "%s: returning\n", __func__); + return 0; +} + +/** + * unmap_context() - clears a previously established mapping + * @ctxi: Context owning the mapping. + * + * This routine is used to switch between the error notification page + * (dummy page of all 1's) and the real mapping (established by the CXL + * fault handler). + */ +static void unmap_context(struct ctx_info *ctxi) +{ + unmap_mapping_range(ctxi->file->f_mapping, 0, 0, 1); +} + +/** + * get_err_page() - obtains and allocates the error notification page + * + * Return: error notification page on success, NULL on failure + */ +static struct page *get_err_page(void) +{ + struct page *err_page = global.err_page; + + if (unlikely(!err_page)) { + err_page = alloc_page(GFP_KERNEL); + if (unlikely(!err_page)) { + pr_err("%s: Unable to allocate err_page!\n", __func__); + goto out; + } + + memset(page_address(err_page), -1, PAGE_SIZE); + + /* Serialize update w/ other threads to avoid a leak */ + mutex_lock(&global.mutex); + if (likely(!global.err_page)) + global.err_page = err_page; + else { + __free_page(err_page); + err_page = global.err_page; + } + mutex_unlock(&global.mutex); + } + +out: + pr_debug("%s: returning err_page=%p\n", __func__, err_page); + return err_page; +} + +/** + * cxlflash_mmap_fault() - mmap fault handler for adapter file descriptor + * @vma: VM area associated with mapping. + * @vmf: VM fault associated with current fault. + * + * To support error notification via MMIO, faults are 'caught' by this routine + * that was inserted before passing back the adapter file descriptor on attach. + * When a fault occurs, this routine evaluates if error recovery is active and + * if so, installs the error page to 'notify' the user about the error state. + * During normal operation, the fault is simply handled by the original fault + * handler that was installed by CXL services as part of initializing the + * adapter file descriptor. The VMA's page protection bits are toggled to + * indicate cached/not-cached depending on the memory backing the fault. + * + * Return: 0 on success, VM_FAULT_SIGBUS on failure + */ +static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct file *file = vma->vm_file; + struct cxl_context *ctx = cxl_fops_get_context(file); + struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg, + cxl_fops); + struct device *dev = &cfg->dev->dev; + struct ctx_info *ctxi = NULL; + struct page *err_page = NULL; + enum ctx_ctrl ctrl = CTX_CTRL_ERR_FALLBACK | CTX_CTRL_FILE; + int rc = 0; + int ctxid; + + ctxid = cxl_process_element(ctx); + if (unlikely(ctxid < 0)) { + dev_err(dev, "%s: Context %p was closed! (%d)\n", + __func__, ctx, ctxid); + goto err; + } + + ctxi = get_context(cfg, ctxid, file, ctrl); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); + goto err; + } + + dev_dbg(dev, "%s: fault(%d) for context %d\n", + __func__, ctxi->lfd, ctxid); + + if (likely(!ctxi->err_recovery_active)) { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + rc = ctxi->cxl_mmap_vmops->fault(vma, vmf); + } else { + dev_dbg(dev, "%s: err recovery active, use err_page!\n", + __func__); + + err_page = get_err_page(); + if (unlikely(!err_page)) { + dev_err(dev, "%s: Could not obtain error page!\n", + __func__); + rc = VM_FAULT_RETRY; + goto out; + } + + get_page(err_page); + vmf->page = err_page; + vma->vm_page_prot = pgprot_cached(vma->vm_page_prot); + } + +out: + if (likely(ctxi)) + put_context(ctxi); + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); + return rc; + +err: + rc = VM_FAULT_SIGBUS; + goto out; +} + +/* + * Local MMAP vmops to 'catch' faults + */ +static const struct vm_operations_struct cxlflash_mmap_vmops = { + .fault = cxlflash_mmap_fault, +}; + +/** + * cxlflash_cxl_mmap() - mmap handler for adapter file descriptor + * @file: File installed with adapter file descriptor. + * @vma: VM area associated with mapping. + * + * Installs local mmap vmops to 'catch' faults for error notification support. + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct cxl_context *ctx = cxl_fops_get_context(file); + struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg, + cxl_fops); + struct device *dev = &cfg->dev->dev; + struct ctx_info *ctxi = NULL; + enum ctx_ctrl ctrl = CTX_CTRL_ERR_FALLBACK | CTX_CTRL_FILE; + int ctxid; + int rc = 0; + + ctxid = cxl_process_element(ctx); + if (unlikely(ctxid < 0)) { + dev_err(dev, "%s: Context %p was closed! (%d)\n", + __func__, ctx, ctxid); + rc = -EIO; + goto out; + } + + ctxi = get_context(cfg, ctxid, file, ctrl); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); + rc = -EIO; + goto out; + } + + dev_dbg(dev, "%s: mmap(%d) for context %d\n", + __func__, ctxi->lfd, ctxid); + + rc = cxl_fd_mmap(file, vma); + if (likely(!rc)) { + /* Insert ourself in the mmap fault handler path */ + ctxi->cxl_mmap_vmops = vma->vm_ops; + vma->vm_ops = &cxlflash_mmap_vmops; + } + +out: + if (likely(ctxi)) + put_context(ctxi); + return rc; +} + +/* + * Local fops for adapter file descriptor + */ +static const struct file_operations cxlflash_cxl_fops = { + .owner = THIS_MODULE, + .mmap = cxlflash_cxl_mmap, + .release = cxlflash_cxl_release, +}; + +/** + * cxlflash_mark_contexts_error() - move contexts to error state and list + * @cfg: Internal structure associated with the host. + * + * A context is only moved over to the error list when there are no outstanding + * references to it. This ensures that a running operation has completed. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_mark_contexts_error(struct cxlflash_cfg *cfg) +{ + int i, rc = 0; + struct ctx_info *ctxi = NULL; + + mutex_lock(&cfg->ctx_tbl_list_mutex); + + for (i = 0; i < MAX_CONTEXT; i++) { + ctxi = cfg->ctx_tbl[i]; + if (ctxi) { + mutex_lock(&ctxi->mutex); + cfg->ctx_tbl[i] = NULL; + list_add(&ctxi->list, &cfg->ctx_err_recovery); + ctxi->err_recovery_active = true; + ctxi->ctrl_map = NULL; + unmap_context(ctxi); + mutex_unlock(&ctxi->mutex); + } + } + + mutex_unlock(&cfg->ctx_tbl_list_mutex); + return rc; +} + +/* + * Dummy NULL fops + */ +static const struct file_operations null_fops = { + .owner = THIS_MODULE, +}; + +/** + * cxlflash_disk_attach() - attach a LUN to a context + * @sdev: SCSI device associated with LUN. + * @attach: Attach ioctl data structure. + * + * Creates a context and attaches LUN to it. A LUN can only be attached + * one time to a context (subsequent attaches for the same context/LUN pair + * are not supported). Additional LUNs can be attached to a context by + * specifying the 'reuse' flag defined in the cxlflash_ioctl.h header. + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_disk_attach(struct scsi_device *sdev, + struct dk_cxlflash_attach *attach) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct cxl_ioctl_start_work *work; + struct ctx_info *ctxi = NULL; + struct lun_access *lun_access = NULL; + int rc = 0; + u32 perms; + int ctxid = -1; + u64 rctxid = 0UL; + struct file *file; + + struct cxl_context *ctx; + + int fd = -1; + + /* On first attach set fileops */ + if (atomic_read(&cfg->num_user_contexts) == 0) + cfg->cxl_fops = cxlflash_cxl_fops; + + if (attach->num_interrupts > 4) { + dev_dbg(dev, "%s: Cannot support this many interrupts %llu\n", + __func__, attach->num_interrupts); + rc = -EINVAL; + goto out; + } + + if (gli->max_lba == 0) { + dev_dbg(dev, "%s: No capacity info for this LUN (%016llX)\n", + __func__, lli->lun_id[sdev->channel]); + rc = read_cap16(sdev, lli); + if (rc) { + dev_err(dev, "%s: Invalid device! (%d)\n", + __func__, rc); + rc = -ENODEV; + goto out; + } + dev_dbg(dev, "%s: LBA = %016llX\n", __func__, gli->max_lba); + dev_dbg(dev, "%s: BLK_LEN = %08X\n", __func__, gli->blk_len); + } + + if (attach->hdr.flags & DK_CXLFLASH_ATTACH_REUSE_CONTEXT) { + rctxid = attach->context_id; + ctxi = get_context(cfg, rctxid, NULL, 0); + if (!ctxi) { + dev_dbg(dev, "%s: Bad context! (%016llX)\n", + __func__, rctxid); + rc = -EINVAL; + goto out; + } + + list_for_each_entry(lun_access, &ctxi->luns, list) + if (lun_access->lli == lli) { + dev_dbg(dev, "%s: Already attached!\n", + __func__); + rc = -EINVAL; + goto out; + } + } + + lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL); + if (unlikely(!lun_access)) { + dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__); + rc = -ENOMEM; + goto out; + } + + lun_access->lli = lli; + lun_access->sdev = sdev; + + /* Non-NULL context indicates reuse */ + if (ctxi) { + dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", + __func__, rctxid); + list_add(&lun_access->list, &ctxi->luns); + fd = ctxi->lfd; + goto out_attach; + } + + ctx = cxl_dev_context_init(cfg->dev); + if (unlikely(IS_ERR_OR_NULL(ctx))) { + dev_err(dev, "%s: Could not initialize context %p\n", + __func__, ctx); + rc = -ENODEV; + goto err0; + } + + ctxid = cxl_process_element(ctx); + if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) { + dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); + rc = -EPERM; + goto err1; + } + + file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd); + if (unlikely(fd < 0)) { + rc = -ENODEV; + dev_err(dev, "%s: Could not get file descriptor\n", __func__); + goto err1; + } + + /* Translate read/write O_* flags from fcntl.h to AFU permission bits */ + perms = SISL_RHT_PERM(attach->hdr.flags + 1); + + ctxi = create_context(cfg, ctx, ctxid, fd, file, perms); + if (unlikely(!ctxi)) { + dev_err(dev, "%s: Failed to create context! (%d)\n", + __func__, ctxid); + goto err2; + } + + work = &ctxi->work; + work->num_interrupts = attach->num_interrupts; + work->flags = CXL_START_WORK_NUM_IRQS; + + rc = cxl_start_work(ctx, work); + if (unlikely(rc)) { + dev_dbg(dev, "%s: Could not start context rc=%d\n", + __func__, rc); + goto err3; + } + + rc = afu_attach(cfg, ctxi); + if (unlikely(rc)) { + dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc); + goto err4; + } + + /* + * No error paths after this point. Once the fd is installed it's + * visible to user space and can't be undone safely on this thread. + * There is no need to worry about a deadlock here because no one + * knows about us yet; we can be the only one holding our mutex. + */ + list_add(&lun_access->list, &ctxi->luns); + mutex_unlock(&ctxi->mutex); + mutex_lock(&cfg->ctx_tbl_list_mutex); + mutex_lock(&ctxi->mutex); + cfg->ctx_tbl[ctxid] = ctxi; + mutex_unlock(&cfg->ctx_tbl_list_mutex); + fd_install(fd, file); + +out_attach: + attach->hdr.return_flags = 0; + attach->context_id = ctxi->ctxid; + attach->block_size = gli->blk_len; + attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); + attach->last_lba = gli->max_lba; + attach->max_xfer = (sdev->host->max_sectors * 512) / gli->blk_len; + +out: + attach->adap_fd = fd; + + if (ctxi) + put_context(ctxi); + + dev_dbg(dev, "%s: returning ctxid=%d fd=%d bs=%lld rc=%d llba=%lld\n", + __func__, ctxid, fd, attach->block_size, rc, attach->last_lba); + return rc; + +err4: + cxl_stop_context(ctx); +err3: + put_context(ctxi); + destroy_context(cfg, ctxi); + ctxi = NULL; +err2: + /* + * Here, we're overriding the fops with a dummy all-NULL fops because + * fput() calls the release fop, which will cause us to mistakenly + * call into the CXL code. Rather than try to add yet more complexity + * to that routine (cxlflash_cxl_release) we should try to fix the + * issue here. + */ + file->f_op = &null_fops; + fput(file); + put_unused_fd(fd); + fd = -1; +err1: + cxl_release_context(ctx); +err0: + kfree(lun_access); + goto out; +} + +/** + * recover_context() - recovers a context in error + * @cfg: Internal structure associated with the host. + * @ctxi: Context to release. + * + * Restablishes the state for a context-in-error. + * + * Return: 0 on success, -errno on failure + */ +static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) +{ + struct device *dev = &cfg->dev->dev; + int rc = 0; + int old_fd, fd = -1; + int ctxid = -1; + struct file *file; + struct cxl_context *ctx; + struct afu *afu = cfg->afu; + + ctx = cxl_dev_context_init(cfg->dev); + if (unlikely(IS_ERR_OR_NULL(ctx))) { + dev_err(dev, "%s: Could not initialize context %p\n", + __func__, ctx); + rc = -ENODEV; + goto out; + } + + ctxid = cxl_process_element(ctx); + if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) { + dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); + rc = -EPERM; + goto err1; + } + + file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd); + if (unlikely(fd < 0)) { + rc = -ENODEV; + dev_err(dev, "%s: Could not get file descriptor\n", __func__); + goto err1; + } + + rc = cxl_start_work(ctx, &ctxi->work); + if (unlikely(rc)) { + dev_dbg(dev, "%s: Could not start context rc=%d\n", + __func__, rc); + goto err2; + } + + /* Update with new MMIO area based on updated context id */ + ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl; + + rc = afu_attach(cfg, ctxi); + if (rc) { + dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc); + goto err3; + } + + /* + * No error paths after this point. Once the fd is installed it's + * visible to user space and can't be undone safely on this thread. + */ + old_fd = ctxi->lfd; + ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); + ctxi->lfd = fd; + ctxi->ctx = ctx; + ctxi->file = file; + + /* + * Put context back in table (note the reinit of the context list); + * we must first drop the context's mutex and then acquire it in + * order with the table/list mutex to avoid a deadlock - safe to do + * here because no one can find us at this moment in time. + */ + mutex_unlock(&ctxi->mutex); + mutex_lock(&cfg->ctx_tbl_list_mutex); + mutex_lock(&ctxi->mutex); + list_del_init(&ctxi->list); + cfg->ctx_tbl[ctxid] = ctxi; + mutex_unlock(&cfg->ctx_tbl_list_mutex); + fd_install(fd, file); + + /* Release the original adapter fd and associated CXL resources */ + sys_close(old_fd); +out: + dev_dbg(dev, "%s: returning ctxid=%d fd=%d rc=%d\n", + __func__, ctxid, fd, rc); + return rc; + +err3: + cxl_stop_context(ctx); +err2: + fput(file); + put_unused_fd(fd); +err1: + cxl_release_context(ctx); + goto out; +} + +/** + * check_state() - checks and responds to the current adapter state + * @cfg: Internal structure associated with the host. + * + * This routine can block and should only be used on process context. + * Note that when waking up from waiting in limbo, the state is unknown + * and must be checked again before proceeding. + * + * Return: 0 on success, -errno on failure + */ +static int check_state(struct cxlflash_cfg *cfg) +{ + struct device *dev = &cfg->dev->dev; + int rc = 0; + +retry: + switch (cfg->state) { + case STATE_LIMBO: + dev_dbg(dev, "%s: Limbo, going to wait...\n", __func__); + rc = wait_event_interruptible(cfg->limbo_waitq, + cfg->state != STATE_LIMBO); + if (unlikely(rc)) + break; + goto retry; + case STATE_FAILTERM: + dev_dbg(dev, "%s: Failed/Terminating!\n", __func__); + rc = -ENODEV; + break; + default: + break; + } + + return rc; +} + +/** + * cxlflash_afu_recover() - initiates AFU recovery + * @sdev: SCSI device associated with LUN. + * @recover: Recover ioctl data structure. + * + * Only a single recovery is allowed at a time to avoid exhausting CXL + * resources (leading to recovery failure) in the event that we're up + * against the maximum number of contexts limit. For similar reasons, + * a context recovery is retried if there are multiple recoveries taking + * place at the same time and the failure was due to CXL services being + * unable to keep up. + * + * Because a user can detect an error condition before the kernel, it is + * quite possible for this routine to act as the kernel's EEH detection + * source (MMIO read of mbox_r). Because of this, there is a window of + * time where an EEH might have been detected but not yet 'serviced' + * (callback invoked, causing the device to enter limbo state). To avoid + * looping in this routine during that window, a 1 second sleep is in place + * between the time the MMIO failure is detected and the time a wait on the + * limbo wait queue is attempted via check_state(). + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_afu_recover(struct scsi_device *sdev, + struct dk_cxlflash_recover_afu *recover) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct afu *afu = cfg->afu; + struct ctx_info *ctxi = NULL; + struct mutex *mutex = &cfg->ctx_recovery_mutex; + u64 ctxid = DECODE_CTXID(recover->context_id), + rctxid = recover->context_id; + long reg; + int lretry = 20; /* up to 2 seconds */ + int rc = 0; + + atomic_inc(&cfg->recovery_threads); + rc = mutex_lock_interruptible(mutex); + if (rc) + goto out; + + dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", + __func__, recover->reason, rctxid); + +retry: + /* Ensure that this process is attached to the context */ + ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); + rc = -EINVAL; + goto out; + } + + if (ctxi->err_recovery_active) { +retry_recover: + rc = recover_context(cfg, ctxi); + if (unlikely(rc)) { + dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", + __func__, ctxid, rc); + if ((rc == -ENODEV) && + ((atomic_read(&cfg->recovery_threads) > 1) || + (lretry--))) { + dev_dbg(dev, "%s: Going to try again!\n", + __func__); + mutex_unlock(mutex); + msleep(100); + rc = mutex_lock_interruptible(mutex); + if (rc) + goto out; + goto retry_recover; + } + + goto out; + } + + ctxi->err_recovery_active = false; + recover->context_id = ctxi->ctxid; + recover->adap_fd = ctxi->lfd; + recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea); + recover->hdr.return_flags |= + DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; + goto out; + } + + /* Test if in error state */ + reg = readq_be(&afu->ctrl_map->mbox_r); + if (reg == -1) { + dev_dbg(dev, "%s: MMIO read fail! Wait for recovery...\n", + __func__); + mutex_unlock(&ctxi->mutex); + ctxi = NULL; + ssleep(1); + rc = check_state(cfg); + if (unlikely(rc)) + goto out; + goto retry; + } + + dev_dbg(dev, "%s: MMIO working, no recovery required!\n", __func__); +out: + if (likely(ctxi)) + put_context(ctxi); + mutex_unlock(mutex); + atomic_dec_if_positive(&cfg->recovery_threads); + return rc; +} + +/** + * process_sense() - evaluates and processes sense data + * @sdev: SCSI device associated with LUN. + * @verify: Verify ioctl data structure. + * + * Return: 0 on success, -errno on failure + */ +static int process_sense(struct scsi_device *sdev, + struct dk_cxlflash_verify *verify) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + u64 prev_lba = gli->max_lba; + struct scsi_sense_hdr sshdr = { 0 }; + int rc = 0; + + rc = scsi_normalize_sense((const u8 *)&verify->sense_data, + DK_CXLFLASH_VERIFY_SENSE_LEN, &sshdr); + if (!rc) { + dev_err(dev, "%s: Failed to normalize sense data!\n", __func__); + rc = -EINVAL; + goto out; + } + + switch (sshdr.sense_key) { + case NO_SENSE: + case RECOVERED_ERROR: + /* fall through */ + case NOT_READY: + break; + case UNIT_ATTENTION: + switch (sshdr.asc) { + case 0x29: /* Power on Reset or Device Reset */ + /* fall through */ + case 0x2A: /* Device settings/capacity changed */ + rc = read_cap16(sdev, lli); + if (rc) { + rc = -ENODEV; + break; + } + if (prev_lba != gli->max_lba) + dev_dbg(dev, "%s: Capacity changed old=%lld " + "new=%lld\n", __func__, prev_lba, + gli->max_lba); + break; + case 0x3F: /* Report LUNs changed, Rescan. */ + scsi_scan_host(cfg->host); + break; + default: + rc = -EIO; + break; + } + break; + default: + rc = -EIO; + break; + } +out: + dev_dbg(dev, "%s: sense_key %x asc %x ascq %x rc %d\n", __func__, + sshdr.sense_key, sshdr.asc, sshdr.ascq, rc); + return rc; +} + +/** + * cxlflash_disk_verify() - verifies a LUN is the same and handle size changes + * @sdev: SCSI device associated with LUN. + * @verify: Verify ioctl data structure. + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_disk_verify(struct scsi_device *sdev, + struct dk_cxlflash_verify *verify) +{ + int rc = 0; + struct ctx_info *ctxi = NULL; + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct sisl_rht_entry *rhte = NULL; + res_hndl_t rhndl = verify->rsrc_handle; + u64 ctxid = DECODE_CTXID(verify->context_id), + rctxid = verify->context_id; + u64 last_lba = 0; + + dev_dbg(dev, "%s: ctxid=%llu rhndl=%016llX, hint=%016llX, " + "flags=%016llX\n", __func__, ctxid, verify->rsrc_handle, + verify->hint, verify->hdr.flags); + + ctxi = get_context(cfg, rctxid, lli, 0); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); + rc = -EINVAL; + goto out; + } + + rhte = get_rhte(ctxi, rhndl, lli); + if (unlikely(!rhte)) { + dev_dbg(dev, "%s: Bad resource handle! (%d)\n", + __func__, rhndl); + rc = -EINVAL; + goto out; + } + + /* + * Look at the hint/sense to see if it requires us to redrive + * inquiry (i.e. the Unit attention is due to the WWN changing). + */ + if (verify->hint & DK_CXLFLASH_VERIFY_HINT_SENSE) { + rc = process_sense(sdev, verify); + if (unlikely(rc)) { + dev_err(dev, "%s: Failed to validate sense data (%d)\n", + __func__, rc); + goto out; + } + } + + switch (gli->mode) { + case MODE_PHYSICAL: + last_lba = gli->max_lba; + break; + default: + WARN(1, "Unsupported LUN mode!"); + } + + verify->last_lba = last_lba; + +out: + if (likely(ctxi)) + put_context(ctxi); + dev_dbg(dev, "%s: returning rc=%d llba=%llX\n", + __func__, rc, verify->last_lba); + return rc; +} + +/** + * decode_ioctl() - translates an encoded ioctl to an easily identifiable string + * @cmd: The ioctl command to decode. + * + * Return: A string identifying the decoded ioctl. + */ +static char *decode_ioctl(int cmd) +{ + switch (cmd) { + case DK_CXLFLASH_ATTACH: + return __stringify_1(DK_CXLFLASH_ATTACH); + case DK_CXLFLASH_USER_DIRECT: + return __stringify_1(DK_CXLFLASH_USER_DIRECT); + case DK_CXLFLASH_RELEASE: + return __stringify_1(DK_CXLFLASH_RELEASE); + case DK_CXLFLASH_DETACH: + return __stringify_1(DK_CXLFLASH_DETACH); + case DK_CXLFLASH_VERIFY: + return __stringify_1(DK_CXLFLASH_VERIFY); + case DK_CXLFLASH_RECOVER_AFU: + return __stringify_1(DK_CXLFLASH_RECOVER_AFU); + case DK_CXLFLASH_MANAGE_LUN: + return __stringify_1(DK_CXLFLASH_MANAGE_LUN); + } + + return "UNKNOWN"; +} + +/** + * cxlflash_disk_direct_open() - opens a direct (physical) disk + * @sdev: SCSI device associated with LUN. + * @arg: UDirect ioctl data structure. + * + * On successful return, the user is informed of the resource handle + * to be used to identify the direct lun and the size (in blocks) of + * the direct lun in last LBA format. + * + * Return: 0 on success, -errno on failure + */ +static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + + struct dk_cxlflash_udirect *pphys = (struct dk_cxlflash_udirect *)arg; + + u64 ctxid = DECODE_CTXID(pphys->context_id), + rctxid = pphys->context_id; + u64 lun_size = 0; + u64 last_lba = 0; + u64 rsrc_handle = -1; + u32 port = CHAN2PORT(sdev->channel); + + int rc = 0; + + struct ctx_info *ctxi = NULL; + struct sisl_rht_entry *rhte = NULL; + + pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); + + rc = cxlflash_lun_attach(gli, MODE_PHYSICAL, false); + if (unlikely(rc)) { + dev_dbg(dev, "%s: Failed to attach to LUN! (PHYSICAL)\n", + __func__); + goto out; + } + + ctxi = get_context(cfg, rctxid, lli, 0); + if (unlikely(!ctxi)) { + dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); + rc = -EINVAL; + goto err1; + } + + rhte = rhte_checkout(ctxi, lli); + if (unlikely(!rhte)) { + dev_dbg(dev, "%s: too many opens for this context\n", __func__); + rc = -EMFILE; /* too many opens */ + goto err1; + } + + rsrc_handle = (rhte - ctxi->rht_start); + + rht_format1(rhte, lli->lun_id[sdev->channel], ctxi->rht_perms, port); + cxlflash_afu_sync(afu, ctxid, rsrc_handle, AFU_LW_SYNC); + + last_lba = gli->max_lba; + pphys->hdr.return_flags = 0; + pphys->last_lba = last_lba; + pphys->rsrc_handle = rsrc_handle; + +out: + if (likely(ctxi)) + put_context(ctxi); + dev_dbg(dev, "%s: returning handle 0x%llx rc=%d llba %lld\n", + __func__, rsrc_handle, rc, last_lba); + return rc; + +err1: + cxlflash_lun_detach(gli); + goto out; +} + +/** + * ioctl_common() - common IOCTL handler for driver + * @sdev: SCSI device associated with LUN. + * @cmd: IOCTL command. + * + * Handles common fencing operations that are valid for multiple ioctls. Always + * allow through ioctls that are cleanup oriented in nature, even when operating + * in a failed/terminating state. + * + * Return: 0 on success, -errno on failure + */ +static int ioctl_common(struct scsi_device *sdev, int cmd) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + int rc = 0; + + if (unlikely(!lli)) { + dev_dbg(dev, "%s: Unknown LUN\n", __func__); + rc = -EINVAL; + goto out; + } + + rc = check_state(cfg); + if (unlikely(rc) && (cfg->state == STATE_FAILTERM)) { + switch (cmd) { + case DK_CXLFLASH_RELEASE: + case DK_CXLFLASH_DETACH: + dev_dbg(dev, "%s: Command override! (%d)\n", + __func__, rc); + rc = 0; + break; + } + } +out: + return rc; +} + +/** + * cxlflash_ioctl() - IOCTL handler for driver + * @sdev: SCSI device associated with LUN. + * @cmd: IOCTL command. + * @arg: Userspace ioctl data structure. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + typedef int (*sioctl) (struct scsi_device *, void *); + + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct afu *afu = cfg->afu; + struct dk_cxlflash_hdr *hdr; + char buf[sizeof(union cxlflash_ioctls)]; + size_t size = 0; + bool known_ioctl = false; + int idx; + int rc = 0; + struct Scsi_Host *shost = sdev->host; + sioctl do_ioctl = NULL; + + static const struct { + size_t size; + sioctl ioctl; + } ioctl_tbl[] = { /* NOTE: order matters here */ + {sizeof(struct dk_cxlflash_attach), (sioctl)cxlflash_disk_attach}, + {sizeof(struct dk_cxlflash_udirect), cxlflash_disk_direct_open}, + {sizeof(struct dk_cxlflash_release), (sioctl)cxlflash_disk_release}, + {sizeof(struct dk_cxlflash_detach), (sioctl)cxlflash_disk_detach}, + {sizeof(struct dk_cxlflash_verify), (sioctl)cxlflash_disk_verify}, + {sizeof(struct dk_cxlflash_recover_afu), (sioctl)cxlflash_afu_recover}, + {sizeof(struct dk_cxlflash_manage_lun), (sioctl)cxlflash_manage_lun}, + }; + + /* Restrict command set to physical support only for internal LUN */ + if (afu->internal_lun) + switch (cmd) { + case DK_CXLFLASH_RELEASE: + dev_dbg(dev, "%s: %s not supported for lun_mode=%d\n", + __func__, decode_ioctl(cmd), afu->internal_lun); + rc = -EINVAL; + goto cxlflash_ioctl_exit; + } + + switch (cmd) { + case DK_CXLFLASH_ATTACH: + case DK_CXLFLASH_USER_DIRECT: + case DK_CXLFLASH_RELEASE: + case DK_CXLFLASH_DETACH: + case DK_CXLFLASH_VERIFY: + case DK_CXLFLASH_RECOVER_AFU: + dev_dbg(dev, "%s: %s (%08X) on dev(%d/%d/%d/%llu)\n", + __func__, decode_ioctl(cmd), cmd, shost->host_no, + sdev->channel, sdev->id, sdev->lun); + rc = ioctl_common(sdev, cmd); + if (unlikely(rc)) + goto cxlflash_ioctl_exit; + + /* fall through */ + + case DK_CXLFLASH_MANAGE_LUN: + known_ioctl = true; + idx = _IOC_NR(cmd) - _IOC_NR(DK_CXLFLASH_ATTACH); + size = ioctl_tbl[idx].size; + do_ioctl = ioctl_tbl[idx].ioctl; + + if (likely(do_ioctl)) + break; + + /* fall through */ + default: + rc = -EINVAL; + goto cxlflash_ioctl_exit; + } + + if (unlikely(copy_from_user(&buf, arg, size))) { + dev_err(dev, "%s: copy_from_user() fail! " + "size=%lu cmd=%d (%s) arg=%p\n", + __func__, size, cmd, decode_ioctl(cmd), arg); + rc = -EFAULT; + goto cxlflash_ioctl_exit; + } + + hdr = (struct dk_cxlflash_hdr *)&buf; + if (hdr->version != DK_CXLFLASH_VERSION_0) { + dev_dbg(dev, "%s: Version %u not supported for %s\n", + __func__, hdr->version, decode_ioctl(cmd)); + rc = -EINVAL; + goto cxlflash_ioctl_exit; + } + + if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->rsvd[2] || hdr->return_flags) { + dev_dbg(dev, "%s: Reserved/rflags populated!\n", __func__); + rc = -EINVAL; + goto cxlflash_ioctl_exit; + } + + rc = do_ioctl(sdev, (void *)&buf); + if (likely(!rc)) + if (unlikely(copy_to_user(arg, &buf, size))) { + dev_err(dev, "%s: copy_to_user() fail! " + "size=%lu cmd=%d (%s) arg=%p\n", + __func__, size, cmd, decode_ioctl(cmd), arg); + rc = -EFAULT; + } + + /* fall through to exit */ + +cxlflash_ioctl_exit: + if (unlikely(rc && known_ioctl)) + dev_err(dev, "%s: ioctl %s (%08X) on dev(%d/%d/%d/%llu) " + "returned rc %d\n", __func__, + decode_ioctl(cmd), cmd, shost->host_no, + sdev->channel, sdev->id, sdev->lun, rc); + else + dev_dbg(dev, "%s: ioctl %s (%08X) on dev(%d/%d/%d/%llu) " + "returned rc %d\n", __func__, decode_ioctl(cmd), + cmd, shost->host_no, sdev->channel, sdev->id, + sdev->lun, rc); + return rc; +} diff --git a/drivers/scsi/cxlflash/superpipe.h b/drivers/scsi/cxlflash/superpipe.h new file mode 100644 index 000000000000..ae39b9627118 --- /dev/null +++ b/drivers/scsi/cxlflash/superpipe.h @@ -0,0 +1,132 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _CXLFLASH_SUPERPIPE_H +#define _CXLFLASH_SUPERPIPE_H + +extern struct cxlflash_global global; + +/* + * Terminology: use afu (and not adapter) to refer to the HW. + * Adapter is the entire slot and includes PSL out of which + * only the AFU is visible to user space. + */ + +/* Chunk size parms: note sislite minimum chunk size is + 0x10000 LBAs corresponding to a NMASK or 16. +*/ +#define MC_CHUNK_SIZE (1 << MC_RHT_NMASK) /* in LBAs */ + +#define MC_DISCOVERY_TIMEOUT 5 /* 5 secs */ + +#define CHAN2PORT(_x) ((_x) + 1) + +enum lun_mode { + MODE_NONE = 0, + MODE_PHYSICAL +}; + +/* Global (entire driver, spans adapters) lun_info structure */ +struct glun_info { + u64 max_lba; /* from read cap(16) */ + u32 blk_len; /* from read cap(16) */ + enum lun_mode mode; /* NONE, PHYSICAL */ + int users; /* Number of users w/ references to LUN */ + + u8 wwid[16]; + + struct mutex mutex; + + struct list_head list; +}; + +/* Local (per-adapter) lun_info structure */ +struct llun_info { + u64 lun_id[CXLFLASH_NUM_FC_PORTS]; /* from REPORT_LUNS */ + u32 lun_index; /* Index in the LUN table */ + u32 host_no; /* host_no from Scsi_host */ + u32 port_sel; /* What port to use for this LUN */ + bool newly_created; /* Whether the LUN was just discovered */ + + u8 wwid[16]; /* Keep a duplicate copy here? */ + + struct glun_info *parent; /* Pointer to entry in global LUN structure */ + struct scsi_device *sdev; + struct list_head list; +}; + +struct lun_access { + struct llun_info *lli; + struct scsi_device *sdev; + struct list_head list; +}; + +enum ctx_ctrl { + CTX_CTRL_CLONE = (1 << 1), + CTX_CTRL_ERR = (1 << 2), + CTX_CTRL_ERR_FALLBACK = (1 << 3), + CTX_CTRL_NOPID = (1 << 4), + CTX_CTRL_FILE = (1 << 5) +}; + +#define ENCODE_CTXID(_ctx, _id) (((((u64)_ctx) & 0xFFFFFFFF0) << 28) | _id) +#define DECODE_CTXID(_val) (_val & 0xFFFFFFFF) + +struct ctx_info { + struct sisl_ctrl_map *ctrl_map; /* initialized at startup */ + struct sisl_rht_entry *rht_start; /* 1 page (req'd for alignment), + alloc/free on attach/detach */ + u32 rht_out; /* Number of checked out RHT entries */ + u32 rht_perms; /* User-defined permissions for RHT entries */ + struct llun_info **rht_lun; /* Mapping of RHT entries to LUNs */ + + struct cxl_ioctl_start_work work; + u64 ctxid; + int lfd; + pid_t pid; + bool unavail; + bool err_recovery_active; + struct mutex mutex; /* Context protection */ + struct cxl_context *ctx; + struct list_head luns; /* LUNs attached to this context */ + const struct vm_operations_struct *cxl_mmap_vmops; + struct file *file; + struct list_head list; /* Link contexts in error recovery */ +}; + +struct cxlflash_global { + struct mutex mutex; + struct list_head gluns;/* list of glun_info structs */ + struct page *err_page; /* One page of all 0xF for error notification */ +}; + +int cxlflash_disk_release(struct scsi_device *, struct dk_cxlflash_release *); +int _cxlflash_disk_release(struct scsi_device *, struct ctx_info *, + struct dk_cxlflash_release *); + +int cxlflash_lun_attach(struct glun_info *, enum lun_mode, bool); +void cxlflash_lun_detach(struct glun_info *); + +struct ctx_info *get_context(struct cxlflash_cfg *, u64, void *, enum ctx_ctrl); +void put_context(struct ctx_info *); + +struct sisl_rht_entry *get_rhte(struct ctx_info *, res_hndl_t, + struct llun_info *); + +struct sisl_rht_entry *rhte_checkout(struct ctx_info *, struct llun_info *); +void rhte_checkin(struct ctx_info *, struct sisl_rht_entry *); + +int cxlflash_manage_lun(struct scsi_device *, struct dk_cxlflash_manage_lun *); + +#endif /* ifndef _CXLFLASH_SUPERPIPE_H */ diff --git a/include/uapi/scsi/Kbuild b/include/uapi/scsi/Kbuild index 75746d52f208..d791e0ad509d 100644 --- a/include/uapi/scsi/Kbuild +++ b/include/uapi/scsi/Kbuild @@ -3,3 +3,4 @@ header-y += fc/ header-y += scsi_bsg_fc.h header-y += scsi_netlink.h header-y += scsi_netlink_fc.h +header-y += cxlflash_ioctl.h diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h new file mode 100644 index 000000000000..570773406531 --- /dev/null +++ b/include/uapi/scsi/cxlflash_ioctl.h @@ -0,0 +1,140 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _CXLFLASH_IOCTL_H +#define _CXLFLASH_IOCTL_H + +#include + +/* + * Structure and flag definitions CXL Flash superpipe ioctls + */ + +#define DK_CXLFLASH_VERSION_0 0 + +struct dk_cxlflash_hdr { + __u16 version; /* Version data */ + __u16 rsvd[3]; /* Reserved for future use */ + __u64 flags; /* Input flags */ + __u64 return_flags; /* Returned flags */ +}; + +/* + * Notes: + * ----- + * The 'context_id' field of all ioctl structures contains the context + * identifier for a context in the lower 32-bits (upper 32-bits are not + * to be used when identifying a context to the AFU). That said, the value + * in its entirety (all 64-bits) is to be treated as an opaque cookie and + * should be presented as such when issuing ioctls. + * + * For DK_CXLFLASH_ATTACH ioctl, user specifies read/write access + * permissions via the O_RDONLY, O_WRONLY, and O_RDWR flags defined in + * the fcntl.h header file. + */ +#define DK_CXLFLASH_ATTACH_REUSE_CONTEXT 0x8000000000000000ULL + +struct dk_cxlflash_attach { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 num_interrupts; /* Requested number of interrupts */ + __u64 context_id; /* Returned context */ + __u64 mmio_size; /* Returned size of MMIO area */ + __u64 block_size; /* Returned block size, in bytes */ + __u64 adap_fd; /* Returned adapter file descriptor */ + __u64 last_lba; /* Returned last LBA on the device */ + __u64 max_xfer; /* Returned max transfer size, blocks */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +struct dk_cxlflash_detach { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context to detach */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +struct dk_cxlflash_udirect { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context to own physical resources */ + __u64 rsrc_handle; /* Returned resource handle */ + __u64 last_lba; /* Returned last LBA on the device */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +struct dk_cxlflash_release { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context owning resources */ + __u64 rsrc_handle; /* Resource handle to release */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +#define DK_CXLFLASH_VERIFY_SENSE_LEN 18 +#define DK_CXLFLASH_VERIFY_HINT_SENSE 0x8000000000000000ULL + +struct dk_cxlflash_verify { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context owning resources to verify */ + __u64 rsrc_handle; /* Resource handle of LUN */ + __u64 hint; /* Reasons for verify */ + __u64 last_lba; /* Returned last LBA of device */ + __u8 sense_data[DK_CXLFLASH_VERIFY_SENSE_LEN]; /* SCSI sense data */ + __u8 pad[6]; /* Pad to next 8-byte boundary */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +#define DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET 0x8000000000000000ULL + +struct dk_cxlflash_recover_afu { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 reason; /* Reason for recovery request */ + __u64 context_id; /* Context to recover / updated ID */ + __u64 mmio_size; /* Returned size of MMIO area */ + __u64 adap_fd; /* Returned adapter file descriptor */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +#define DK_CXLFLASH_MANAGE_LUN_WWID_LEN 16 +#define DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE 0x8000000000000000ULL +#define DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE 0x4000000000000000ULL +#define DK_CXLFLASH_MANAGE_LUN_ALL_PORTS_ACCESSIBLE 0x2000000000000000ULL + +struct dk_cxlflash_manage_lun { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u8 wwid[DK_CXLFLASH_MANAGE_LUN_WWID_LEN]; /* Page83 WWID, NAA-6 */ + __u64 reserved[8]; /* Rsvd, future use */ +}; + +union cxlflash_ioctls { + struct dk_cxlflash_attach attach; + struct dk_cxlflash_detach detach; + struct dk_cxlflash_udirect udirect; + struct dk_cxlflash_release release; + struct dk_cxlflash_verify verify; + struct dk_cxlflash_recover_afu recover_afu; + struct dk_cxlflash_manage_lun manage_lun; +}; + +#define MAX_CXLFLASH_IOCTL_SZ (sizeof(union cxlflash_ioctls)) + +#define CXL_MAGIC 0xCA +#define CXL_IOWR(_n, _s) _IOWR(CXL_MAGIC, _n, struct _s) + +#define DK_CXLFLASH_ATTACH CXL_IOWR(0x80, dk_cxlflash_attach) +#define DK_CXLFLASH_USER_DIRECT CXL_IOWR(0x81, dk_cxlflash_udirect) +#define DK_CXLFLASH_RELEASE CXL_IOWR(0x82, dk_cxlflash_release) +#define DK_CXLFLASH_DETACH CXL_IOWR(0x83, dk_cxlflash_detach) +#define DK_CXLFLASH_VERIFY CXL_IOWR(0x84, dk_cxlflash_verify) +#define DK_CXLFLASH_RECOVER_AFU CXL_IOWR(0x85, dk_cxlflash_recover_afu) +#define DK_CXLFLASH_MANAGE_LUN CXL_IOWR(0x86, dk_cxlflash_manage_lun) + +#endif /* ifndef _CXLFLASH_IOCTL_H */ From 2cb79266d6b229dbebd31fe114af1bdab25c8076 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Thu, 13 Aug 2015 21:47:53 -0500 Subject: [PATCH 74/85] cxlflash: Virtual LUN support Add support for physical LUN segmentation (virtual LUNs) to device driver supporting the IBM CXL Flash adapter. This patch allows user space applications to virtually segment a physical LUN into N virtual LUNs, taking advantage of the translation features provided by this adapter. Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reviewed-by: Michael Neuling Reviewed-by: Wen Xiong Signed-off-by: James Bottomley --- Documentation/powerpc/cxlflash.txt | 63 +- drivers/scsi/cxlflash/Makefile | 2 +- drivers/scsi/cxlflash/common.h | 4 + drivers/scsi/cxlflash/lunmgt.c | 3 + drivers/scsi/cxlflash/main.c | 13 + drivers/scsi/cxlflash/sislite.h | 20 +- drivers/scsi/cxlflash/superpipe.c | 82 +- drivers/scsi/cxlflash/superpipe.h | 17 +- drivers/scsi/cxlflash/vlun.c | 1243 ++++++++++++++++++++++++++++ drivers/scsi/cxlflash/vlun.h | 86 ++ include/uapi/scsi/cxlflash_ioctl.h | 34 + 11 files changed, 1550 insertions(+), 17 deletions(-) create mode 100644 drivers/scsi/cxlflash/vlun.c create mode 100644 drivers/scsi/cxlflash/vlun.h diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt index f943967f90ce..4202d1bc583c 100644 --- a/Documentation/powerpc/cxlflash.txt +++ b/Documentation/powerpc/cxlflash.txt @@ -163,7 +163,8 @@ DK_CXLFLASH_ATTACH - These tokens are only valid for the process under which they were created. The child of a forked process cannot continue - to use the context id or file descriptor created by its parent. + to use the context id or file descriptor created by its parent + (see DK_CXLFLASH_VLUN_CLONE for further details). - These tokens are only valid for the lifetime of the context and the process under which they were created. Once either is @@ -193,6 +194,45 @@ DK_CXLFLASH_USER_DIRECT treated as a resource handle that is returned to the user. The user is then able to use the handle to reference the LUN during I/O. +DK_CXLFLASH_USER_VIRTUAL +------------------------ + This ioctl is responsible for transitioning the LUN to virtual mode + of access and configuring the AFU for virtual access from user space + on a per-context basis. Additionally, the block size and last logical + block address (LBA) are returned to the user. + + As mentioned previously, when operating in user space access mode, + LUNs may be accessed in whole or in part. Only one mode is allowed + at a time and if one mode is active (outstanding references exist), + requests to use the LUN in a different mode are denied. + + The AFU is configured for virtual access from user space by adding + an entry to the AFU's resource handle table. The index of the entry + is treated as a resource handle that is returned to the user. The + user is then able to use the handle to reference the LUN during I/O. + + By default, the virtual LUN is created with a size of 0. The user + would need to use the DK_CXLFLASH_VLUN_RESIZE ioctl to adjust the grow + the virtual LUN to a desired size. To avoid having to perform this + resize for the initial creation of the virtual LUN, the user has the + option of specifying a size as part of the DK_CXLFLASH_USER_VIRTUAL + ioctl, such that when success is returned to the user, the + resource handle that is provided is already referencing provisioned + storage. This is reflected by the last LBA being a non-zero value. + +DK_CXLFLASH_VLUN_RESIZE +----------------------- + This ioctl is responsible for resizing a previously created virtual + LUN and will fail if invoked upon a LUN that is not in virtual + mode. Upon success, an updated last LBA is returned to the user + indicating the new size of the virtual LUN associated with the + resource handle. + + The partitioning of virtual LUNs is jointly mediated by the cxlflash + driver and the AFU. An allocation table is kept for each LUN that is + operating in the virtual mode and used to program a LUN translation + table that the AFU references when provided with a resource handle. + DK_CXLFLASH_RELEASE ------------------- This ioctl is responsible for releasing a previously obtained @@ -214,6 +254,27 @@ DK_CXLFLASH_DETACH success, all "tokens" which had been provided to the user from the DK_CXLFLASH_ATTACH onward are no longer valid. +DK_CXLFLASH_VLUN_CLONE +---------------------- + This ioctl is responsible for cloning a previously created + context to a more recently created context. It exists solely to + support maintaining user space access to storage after a process + forks. Upon success, the child process (which invoked the ioctl) + will have access to the same LUNs via the same resource handle(s) + and fd2 as the parent, but under a different context. + + Context sharing across processes is not supported with CXL and + therefore each fork must be met with establishing a new context + for the child process. This ioctl simplifies the state management + and playback required by a user in such a scenario. When a process + forks, child process can clone the parents context by first creating + a context (via DK_CXLFLASH_ATTACH) and then using this ioctl to + perform the clone from the parent to the child. + + The clone itself is fairly simple. The resource handle and lun + translation tables are copied from the parent context to the child's + and then synced with the AFU. + DK_CXLFLASH_VERIFY ------------------ This ioctl is used to detect various changes such as the capacity of diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile index c14d24c720d6..9e39866d473b 100644 --- a/drivers/scsi/cxlflash/Makefile +++ b/drivers/scsi/cxlflash/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_CXLFLASH) += cxlflash.o -cxlflash-y += main.o superpipe.o lunmgt.o +cxlflash-y += main.o superpipe.o lunmgt.o vlun.o diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index d3e54e61c7a5..1c56037146e1 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -116,6 +116,9 @@ struct cxlflash_cfg { atomic_t num_user_contexts; + /* Parameters that are LUN table related */ + int last_lun_index[CXLFLASH_NUM_FC_PORTS]; + int promote_lun_index; struct list_head lluns; /* list of llun_info structs */ wait_queue_head_t tmf_waitq; @@ -200,5 +203,6 @@ int cxlflash_ioctl(struct scsi_device *, int, void __user *); void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *); int cxlflash_mark_contexts_error(struct cxlflash_cfg *); void cxlflash_term_local_luns(struct cxlflash_cfg *); +void cxlflash_restore_luntable(struct cxlflash_cfg *); #endif /* ifndef _CXLFLASH_COMMON_H */ diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c index 66d5bef11ee6..d98ad0ff64c1 100644 --- a/drivers/scsi/cxlflash/lunmgt.c +++ b/drivers/scsi/cxlflash/lunmgt.c @@ -20,6 +20,7 @@ #include "sislite.h" #include "common.h" +#include "vlun.h" #include "superpipe.h" /** @@ -42,6 +43,7 @@ static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid) lli->sdev = sdev; lli->newly_created = true; lli->host_no = sdev->host->host_no; + lli->in_table = false; memcpy(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN); out: @@ -208,6 +210,7 @@ void cxlflash_term_global_luns(void) mutex_lock(&global.mutex); list_for_each_entry_safe(gli, temp, &global.gluns, list) { list_del(&gli->list); + cxlflash_ba_terminate(&gli->blka.ba_lun); kfree(gli); } mutex_unlock(&global.mutex); diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 02d464f41b7f..458ed838f83a 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -1989,6 +1989,8 @@ static int init_afu(struct cxlflash_cfg *cfg) afu_err_intr_init(cfg->afu); atomic64_set(&afu->room, readq_be(&afu->host_map->cmd_room)); + /* Restore the LUN mappings */ + cxlflash_restore_luntable(cfg); err1: pr_debug("%s: returning rc=%d\n", __func__, rc); return rc; @@ -2286,6 +2288,17 @@ static int cxlflash_probe(struct pci_dev *pdev, cfg->init_state = INIT_STATE_NONE; cfg->dev = pdev; + + /* + * The promoted LUNs move to the top of the LUN table. The rest stay + * on the bottom half. The bottom half grows from the end + * (index = 255), whereas the top half grows from the beginning + * (index = 0). + */ + cfg->promote_lun_index = 0; + cfg->last_lun_index[0] = CXLFLASH_NUM_VLUNS/2 - 1; + cfg->last_lun_index[1] = CXLFLASH_NUM_VLUNS/2 - 1; + cfg->dev_id = (struct pci_device_id *)dev_id; cfg->mcctx = NULL; diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h index 66b889151a4c..63bf394fe78c 100644 --- a/drivers/scsi/cxlflash/sislite.h +++ b/drivers/scsi/cxlflash/sislite.h @@ -397,16 +397,17 @@ struct cxlflash_afu_map { }; }; -/* LBA translation control blocks */ - +/* + * LXT - LBA Translation Table + * LXT control blocks + */ struct sisl_lxt_entry { u64 rlba_base; /* bits 0:47 is base - * b48:55 is lun index - * b58:59 is write & read perms - * (if no perm, afu_rc=0x15) - * b60:63 is port_sel mask - */ - + * b48:55 is lun index + * b58:59 is write & read perms + * (if no perm, afu_rc=0x15) + * b60:63 is port_sel mask + */ }; /* @@ -465,4 +466,7 @@ struct sisl_rht_entry_f1 { #define TMF_LUN_RESET 0x1U #define TMF_CLEAR_ACA 0x2U + +#define SISLITE_MAX_WS_BLOCKS 512 + #endif /* _SISLITE_H */ diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index 3c8bce8bbb0b..f1b62cea75b1 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c @@ -26,10 +26,24 @@ #include "sislite.h" #include "common.h" +#include "vlun.h" #include "superpipe.h" struct cxlflash_global global; +/** + * marshal_rele_to_resize() - translate release to resize structure + * @rele: Source structure from which to translate/copy. + * @resize: Destination structure for the translate/copy. + */ +static void marshal_rele_to_resize(struct dk_cxlflash_release *release, + struct dk_cxlflash_resize *resize) +{ + resize->hdr = release->hdr; + resize->context_id = release->context_id; + resize->rsrc_handle = release->rsrc_handle; +} + /** * marshal_det_to_rele() - translate detach to release structure * @detach: Destination structure for the translate/copy. @@ -449,6 +463,7 @@ void rhte_checkin(struct ctx_info *ctxi, rhte->fp = 0; ctxi->rht_out--; ctxi->rht_lun[rsrc_handle] = NULL; + ctxi->rht_needs_ws[rsrc_handle] = false; } /** @@ -526,13 +541,21 @@ out: /** * cxlflash_lun_detach() - detaches a user from a LUN and resets the LUN's mode * @gli: LUN to detach. + * + * When resetting the mode, terminate block allocation resources as they + * are no longer required (service is safe to call even when block allocation + * resources were not present - such as when transitioning from physical mode). + * These resources will be reallocated when needed (subsequent transition to + * virtual mode). */ void cxlflash_lun_detach(struct glun_info *gli) { mutex_lock(&gli->mutex); WARN_ON(gli->mode == MODE_NONE); - if (--gli->users == 0) + if (--gli->users == 0) { gli->mode = MODE_NONE; + cxlflash_ba_terminate(&gli->blka.ba_lun); + } pr_debug("%s: gli->users=%u\n", __func__, gli->users); WARN_ON(gli->users < 0); mutex_unlock(&gli->mutex); @@ -544,10 +567,12 @@ void cxlflash_lun_detach(struct glun_info *gli) * @ctxi: Context owning resources. * @release: Release ioctl data structure. * - * Note that the AFU sync should _not_ be performed when the context is sitting - * on the error recovery list. A context on the error recovery list is not known - * to the AFU due to reset. When the context is recovered, it will be reattached - * and made known again to the AFU. + * For LUNs in virtual mode, the virtual LUN associated with the specified + * resource handle is resized to 0 prior to releasing the RHTE. Note that the + * AFU sync should _not_ be performed when the context is sitting on the error + * recovery list. A context on the error recovery list is not known to the AFU + * due to reset. When the context is recovered, it will be reattached and made + * known again to the AFU. * * Return: 0 on success, -errno on failure */ @@ -562,6 +587,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev, struct afu *afu = cfg->afu; bool put_ctx = false; + struct dk_cxlflash_resize size; res_hndl_t rhndl = release->rsrc_handle; int rc = 0; @@ -594,7 +620,24 @@ int _cxlflash_disk_release(struct scsi_device *sdev, goto out; } + /* + * Resize to 0 for virtual LUNS by setting the size + * to 0. This will clear LXT_START and LXT_CNT fields + * in the RHT entry and properly sync with the AFU. + * + * Afterwards we clear the remaining fields. + */ switch (gli->mode) { + case MODE_VIRTUAL: + marshal_rele_to_resize(release, &size); + size.req_size = 0; + rc = _cxlflash_vlun_resize(sdev, ctxi, &size); + if (rc) { + dev_dbg(dev, "%s: resize failed rc %d\n", __func__, rc); + goto out; + } + + break; case MODE_PHYSICAL: /* * Clear the Format 1 RHT entry for direct access @@ -666,6 +709,7 @@ static void destroy_context(struct cxlflash_cfg *cfg, /* Free memory associated with context */ free_page((ulong)ctxi->rht_start); + kfree(ctxi->rht_needs_ws); kfree(ctxi->rht_lun); kfree(ctxi); atomic_dec_if_positive(&cfg->num_user_contexts); @@ -693,11 +737,13 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg, struct afu *afu = cfg->afu; struct ctx_info *ctxi = NULL; struct llun_info **lli = NULL; + bool *ws = NULL; struct sisl_rht_entry *rhte; ctxi = kzalloc(sizeof(*ctxi), GFP_KERNEL); lli = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*lli)), GFP_KERNEL); - if (unlikely(!ctxi || !lli)) { + ws = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*ws)), GFP_KERNEL); + if (unlikely(!ctxi || !lli || !ws)) { dev_err(dev, "%s: Unable to allocate context!\n", __func__); goto err; } @@ -709,6 +755,7 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg, } ctxi->rht_lun = lli; + ctxi->rht_needs_ws = ws; ctxi->rht_start = rhte; ctxi->rht_perms = perms; @@ -728,6 +775,7 @@ out: return ctxi; err: + kfree(ws); kfree(lli); kfree(ctxi); ctxi = NULL; @@ -1729,6 +1777,12 @@ static int cxlflash_disk_verify(struct scsi_device *sdev, case MODE_PHYSICAL: last_lba = gli->max_lba; break; + case MODE_VIRTUAL: + /* Cast lxt_cnt to u64 for multiply to be treated as 64bit op */ + last_lba = ((u64)rhte->lxt_cnt * MC_CHUNK_SIZE * gli->blk_len); + last_lba /= CXLFLASH_BLOCK_SIZE; + last_lba--; + break; default: WARN(1, "Unsupported LUN mode!"); } @@ -1756,12 +1810,18 @@ static char *decode_ioctl(int cmd) return __stringify_1(DK_CXLFLASH_ATTACH); case DK_CXLFLASH_USER_DIRECT: return __stringify_1(DK_CXLFLASH_USER_DIRECT); + case DK_CXLFLASH_USER_VIRTUAL: + return __stringify_1(DK_CXLFLASH_USER_VIRTUAL); + case DK_CXLFLASH_VLUN_RESIZE: + return __stringify_1(DK_CXLFLASH_VLUN_RESIZE); case DK_CXLFLASH_RELEASE: return __stringify_1(DK_CXLFLASH_RELEASE); case DK_CXLFLASH_DETACH: return __stringify_1(DK_CXLFLASH_DETACH); case DK_CXLFLASH_VERIFY: return __stringify_1(DK_CXLFLASH_VERIFY); + case DK_CXLFLASH_VLUN_CLONE: + return __stringify_1(DK_CXLFLASH_VLUN_CLONE); case DK_CXLFLASH_RECOVER_AFU: return __stringify_1(DK_CXLFLASH_RECOVER_AFU); case DK_CXLFLASH_MANAGE_LUN: @@ -1876,6 +1936,7 @@ static int ioctl_common(struct scsi_device *sdev, int cmd) rc = check_state(cfg); if (unlikely(rc) && (cfg->state == STATE_FAILTERM)) { switch (cmd) { + case DK_CXLFLASH_VLUN_RESIZE: case DK_CXLFLASH_RELEASE: case DK_CXLFLASH_DETACH: dev_dbg(dev, "%s: Command override! (%d)\n", @@ -1923,12 +1984,18 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) {sizeof(struct dk_cxlflash_verify), (sioctl)cxlflash_disk_verify}, {sizeof(struct dk_cxlflash_recover_afu), (sioctl)cxlflash_afu_recover}, {sizeof(struct dk_cxlflash_manage_lun), (sioctl)cxlflash_manage_lun}, + {sizeof(struct dk_cxlflash_uvirtual), cxlflash_disk_virtual_open}, + {sizeof(struct dk_cxlflash_resize), (sioctl)cxlflash_vlun_resize}, + {sizeof(struct dk_cxlflash_clone), (sioctl)cxlflash_disk_clone}, }; /* Restrict command set to physical support only for internal LUN */ if (afu->internal_lun) switch (cmd) { case DK_CXLFLASH_RELEASE: + case DK_CXLFLASH_USER_VIRTUAL: + case DK_CXLFLASH_VLUN_RESIZE: + case DK_CXLFLASH_VLUN_CLONE: dev_dbg(dev, "%s: %s not supported for lun_mode=%d\n", __func__, decode_ioctl(cmd), afu->internal_lun); rc = -EINVAL; @@ -1942,6 +2009,9 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) case DK_CXLFLASH_DETACH: case DK_CXLFLASH_VERIFY: case DK_CXLFLASH_RECOVER_AFU: + case DK_CXLFLASH_USER_VIRTUAL: + case DK_CXLFLASH_VLUN_RESIZE: + case DK_CXLFLASH_VLUN_CLONE: dev_dbg(dev, "%s: %s (%08X) on dev(%d/%d/%d/%llu)\n", __func__, decode_ioctl(cmd), cmd, shost->host_no, sdev->channel, sdev->id, sdev->lun); diff --git a/drivers/scsi/cxlflash/superpipe.h b/drivers/scsi/cxlflash/superpipe.h index ae39b9627118..d7dc88bc64a4 100644 --- a/drivers/scsi/cxlflash/superpipe.h +++ b/drivers/scsi/cxlflash/superpipe.h @@ -31,9 +31,11 @@ extern struct cxlflash_global global; #define MC_DISCOVERY_TIMEOUT 5 /* 5 secs */ #define CHAN2PORT(_x) ((_x) + 1) +#define PORT2CHAN(_x) ((_x) - 1) enum lun_mode { MODE_NONE = 0, + MODE_VIRTUAL, MODE_PHYSICAL }; @@ -41,13 +43,14 @@ enum lun_mode { struct glun_info { u64 max_lba; /* from read cap(16) */ u32 blk_len; /* from read cap(16) */ - enum lun_mode mode; /* NONE, PHYSICAL */ + enum lun_mode mode; /* NONE, VIRTUAL, PHYSICAL */ int users; /* Number of users w/ references to LUN */ u8 wwid[16]; struct mutex mutex; + struct blka blka; struct list_head list; }; @@ -58,6 +61,7 @@ struct llun_info { u32 host_no; /* host_no from Scsi_host */ u32 port_sel; /* What port to use for this LUN */ bool newly_created; /* Whether the LUN was just discovered */ + bool in_table; /* Whether a LUN table entry was created */ u8 wwid[16]; /* Keep a duplicate copy here? */ @@ -90,6 +94,7 @@ struct ctx_info { u32 rht_out; /* Number of checked out RHT entries */ u32 rht_perms; /* User-defined permissions for RHT entries */ struct llun_info **rht_lun; /* Mapping of RHT entries to LUNs */ + bool *rht_needs_ws; /* User-desired write-same function per RHTE */ struct cxl_ioctl_start_work work; u64 ctxid; @@ -111,10 +116,18 @@ struct cxlflash_global { struct page *err_page; /* One page of all 0xF for error notification */ }; +int cxlflash_vlun_resize(struct scsi_device *, struct dk_cxlflash_resize *); +int _cxlflash_vlun_resize(struct scsi_device *, struct ctx_info *, + struct dk_cxlflash_resize *); + int cxlflash_disk_release(struct scsi_device *, struct dk_cxlflash_release *); int _cxlflash_disk_release(struct scsi_device *, struct ctx_info *, struct dk_cxlflash_release *); +int cxlflash_disk_clone(struct scsi_device *, struct dk_cxlflash_clone *); + +int cxlflash_disk_virtual_open(struct scsi_device *, void *); + int cxlflash_lun_attach(struct glun_info *, enum lun_mode, bool); void cxlflash_lun_detach(struct glun_info *); @@ -127,6 +140,8 @@ struct sisl_rht_entry *get_rhte(struct ctx_info *, res_hndl_t, struct sisl_rht_entry *rhte_checkout(struct ctx_info *, struct llun_info *); void rhte_checkin(struct ctx_info *, struct sisl_rht_entry *); +void cxlflash_ba_terminate(struct ba_lun *); + int cxlflash_manage_lun(struct scsi_device *, struct dk_cxlflash_manage_lun *); #endif /* ifndef _CXLFLASH_SUPERPIPE_H */ diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c new file mode 100644 index 000000000000..6155cb1d4ed3 --- /dev/null +++ b/drivers/scsi/cxlflash/vlun.c @@ -0,0 +1,1243 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "sislite.h" +#include "common.h" +#include "vlun.h" +#include "superpipe.h" + +/** + * marshal_virt_to_resize() - translate uvirtual to resize structure + * @virt: Source structure from which to translate/copy. + * @resize: Destination structure for the translate/copy. + */ +static void marshal_virt_to_resize(struct dk_cxlflash_uvirtual *virt, + struct dk_cxlflash_resize *resize) +{ + resize->hdr = virt->hdr; + resize->context_id = virt->context_id; + resize->rsrc_handle = virt->rsrc_handle; + resize->req_size = virt->lun_size; + resize->last_lba = virt->last_lba; +} + +/** + * marshal_clone_to_rele() - translate clone to release structure + * @clone: Source structure from which to translate/copy. + * @rele: Destination structure for the translate/copy. + */ +static void marshal_clone_to_rele(struct dk_cxlflash_clone *clone, + struct dk_cxlflash_release *release) +{ + release->hdr = clone->hdr; + release->context_id = clone->context_id_dst; +} + +/** + * ba_init() - initializes a block allocator + * @ba_lun: Block allocator to initialize. + * + * Return: 0 on success, -errno on failure + */ +static int ba_init(struct ba_lun *ba_lun) +{ + struct ba_lun_info *bali = NULL; + int lun_size_au = 0, i = 0; + int last_word_underflow = 0; + u64 *lam; + + pr_debug("%s: Initializing LUN: lun_id = %llX, " + "ba_lun->lsize = %lX, ba_lun->au_size = %lX\n", + __func__, ba_lun->lun_id, ba_lun->lsize, ba_lun->au_size); + + /* Calculate bit map size */ + lun_size_au = ba_lun->lsize / ba_lun->au_size; + if (lun_size_au == 0) { + pr_debug("%s: Requested LUN size of 0!\n", __func__); + return -EINVAL; + } + + /* Allocate lun information container */ + bali = kzalloc(sizeof(struct ba_lun_info), GFP_KERNEL); + if (unlikely(!bali)) { + pr_err("%s: Failed to allocate lun_info for lun_id %llX\n", + __func__, ba_lun->lun_id); + return -ENOMEM; + } + + bali->total_aus = lun_size_au; + bali->lun_bmap_size = lun_size_au / BITS_PER_LONG; + + if (lun_size_au % BITS_PER_LONG) + bali->lun_bmap_size++; + + /* Allocate bitmap space */ + bali->lun_alloc_map = kzalloc((bali->lun_bmap_size * sizeof(u64)), + GFP_KERNEL); + if (unlikely(!bali->lun_alloc_map)) { + pr_err("%s: Failed to allocate lun allocation map: " + "lun_id = %llX\n", __func__, ba_lun->lun_id); + kfree(bali); + return -ENOMEM; + } + + /* Initialize the bit map size and set all bits to '1' */ + bali->free_aun_cnt = lun_size_au; + + for (i = 0; i < bali->lun_bmap_size; i++) + bali->lun_alloc_map[i] = 0xFFFFFFFFFFFFFFFFULL; + + /* If the last word not fully utilized, mark extra bits as allocated */ + last_word_underflow = (bali->lun_bmap_size * BITS_PER_LONG); + last_word_underflow -= bali->free_aun_cnt; + if (last_word_underflow > 0) { + lam = &bali->lun_alloc_map[bali->lun_bmap_size - 1]; + for (i = (HIBIT - last_word_underflow + 1); + i < BITS_PER_LONG; + i++) + clear_bit(i, (ulong *)lam); + } + + /* Initialize high elevator index, low/curr already at 0 from kzalloc */ + bali->free_high_idx = bali->lun_bmap_size; + + /* Allocate clone map */ + bali->aun_clone_map = kzalloc((bali->total_aus * sizeof(u8)), + GFP_KERNEL); + if (unlikely(!bali->aun_clone_map)) { + pr_err("%s: Failed to allocate clone map: lun_id = %llX\n", + __func__, ba_lun->lun_id); + kfree(bali->lun_alloc_map); + kfree(bali); + return -ENOMEM; + } + + /* Pass the allocated lun info as a handle to the user */ + ba_lun->ba_lun_handle = bali; + + pr_debug("%s: Successfully initialized the LUN: " + "lun_id = %llX, bitmap size = %X, free_aun_cnt = %llX\n", + __func__, ba_lun->lun_id, bali->lun_bmap_size, + bali->free_aun_cnt); + return 0; +} + +/** + * find_free_range() - locates a free bit within the block allocator + * @low: First word in block allocator to start search. + * @high: Last word in block allocator to search. + * @bali: LUN information structure owning the block allocator to search. + * @bit_word: Passes back the word in the block allocator owning the free bit. + * + * Return: The bit position within the passed back word, -1 on failure + */ +static int find_free_range(u32 low, + u32 high, + struct ba_lun_info *bali, int *bit_word) +{ + int i; + u64 bit_pos = -1; + ulong *lam, num_bits; + + for (i = low; i < high; i++) + if (bali->lun_alloc_map[i] != 0) { + lam = (ulong *)&bali->lun_alloc_map[i]; + num_bits = (sizeof(*lam) * BITS_PER_BYTE); + bit_pos = find_first_bit(lam, num_bits); + + pr_devel("%s: Found free bit %llX in lun " + "map entry %llX at bitmap index = %X\n", + __func__, bit_pos, bali->lun_alloc_map[i], + i); + + *bit_word = i; + bali->free_aun_cnt--; + clear_bit(bit_pos, lam); + break; + } + + return bit_pos; +} + +/** + * ba_alloc() - allocates a block from the block allocator + * @ba_lun: Block allocator from which to allocate a block. + * + * Return: The allocated block, -1 on failure + */ +static u64 ba_alloc(struct ba_lun *ba_lun) +{ + u64 bit_pos = -1; + int bit_word = 0; + struct ba_lun_info *bali = NULL; + + bali = ba_lun->ba_lun_handle; + + pr_debug("%s: Received block allocation request: " + "lun_id = %llX, free_aun_cnt = %llX\n", + __func__, ba_lun->lun_id, bali->free_aun_cnt); + + if (bali->free_aun_cnt == 0) { + pr_debug("%s: No space left on LUN: lun_id = %llX\n", + __func__, ba_lun->lun_id); + return -1ULL; + } + + /* Search to find a free entry, curr->high then low->curr */ + bit_pos = find_free_range(bali->free_curr_idx, + bali->free_high_idx, bali, &bit_word); + if (bit_pos == -1) { + bit_pos = find_free_range(bali->free_low_idx, + bali->free_curr_idx, + bali, &bit_word); + if (bit_pos == -1) { + pr_debug("%s: Could not find an allocation unit on LUN:" + " lun_id = %llX\n", __func__, ba_lun->lun_id); + return -1ULL; + } + } + + /* Update the free_curr_idx */ + if (bit_pos == HIBIT) + bali->free_curr_idx = bit_word + 1; + else + bali->free_curr_idx = bit_word; + + pr_debug("%s: Allocating AU number %llX, on lun_id %llX, " + "free_aun_cnt = %llX\n", __func__, + ((bit_word * BITS_PER_LONG) + bit_pos), ba_lun->lun_id, + bali->free_aun_cnt); + + return (u64) ((bit_word * BITS_PER_LONG) + bit_pos); +} + +/** + * validate_alloc() - validates the specified block has been allocated + * @ba_lun_info: LUN info owning the block allocator. + * @aun: Block to validate. + * + * Return: 0 on success, -1 on failure + */ +static int validate_alloc(struct ba_lun_info *bali, u64 aun) +{ + int idx = 0, bit_pos = 0; + + idx = aun / BITS_PER_LONG; + bit_pos = aun % BITS_PER_LONG; + + if (test_bit(bit_pos, (ulong *)&bali->lun_alloc_map[idx])) + return -1; + + return 0; +} + +/** + * ba_free() - frees a block from the block allocator + * @ba_lun: Block allocator from which to allocate a block. + * @to_free: Block to free. + * + * Return: 0 on success, -1 on failure + */ +static int ba_free(struct ba_lun *ba_lun, u64 to_free) +{ + int idx = 0, bit_pos = 0; + struct ba_lun_info *bali = NULL; + + bali = ba_lun->ba_lun_handle; + + if (validate_alloc(bali, to_free)) { + pr_debug("%s: The AUN %llX is not allocated on lun_id %llX\n", + __func__, to_free, ba_lun->lun_id); + return -1; + } + + pr_debug("%s: Received a request to free AU %llX on lun_id %llX, " + "free_aun_cnt = %llX\n", __func__, to_free, ba_lun->lun_id, + bali->free_aun_cnt); + + if (bali->aun_clone_map[to_free] > 0) { + pr_debug("%s: AUN %llX on lun_id %llX has been cloned. Clone " + "count = %X\n", __func__, to_free, ba_lun->lun_id, + bali->aun_clone_map[to_free]); + bali->aun_clone_map[to_free]--; + return 0; + } + + idx = to_free / BITS_PER_LONG; + bit_pos = to_free % BITS_PER_LONG; + + set_bit(bit_pos, (ulong *)&bali->lun_alloc_map[idx]); + bali->free_aun_cnt++; + + if (idx < bali->free_low_idx) + bali->free_low_idx = idx; + else if (idx > bali->free_high_idx) + bali->free_high_idx = idx; + + pr_debug("%s: Successfully freed AU at bit_pos %X, bit map index %X on " + "lun_id %llX, free_aun_cnt = %llX\n", __func__, bit_pos, idx, + ba_lun->lun_id, bali->free_aun_cnt); + + return 0; +} + +/** + * ba_clone() - Clone a chunk of the block allocation table + * @ba_lun: Block allocator from which to allocate a block. + * @to_free: Block to free. + * + * Return: 0 on success, -1 on failure + */ +static int ba_clone(struct ba_lun *ba_lun, u64 to_clone) +{ + struct ba_lun_info *bali = ba_lun->ba_lun_handle; + + if (validate_alloc(bali, to_clone)) { + pr_debug("%s: AUN %llX is not allocated on lun_id %llX\n", + __func__, to_clone, ba_lun->lun_id); + return -1; + } + + pr_debug("%s: Received a request to clone AUN %llX on lun_id %llX\n", + __func__, to_clone, ba_lun->lun_id); + + if (bali->aun_clone_map[to_clone] == MAX_AUN_CLONE_CNT) { + pr_debug("%s: AUN %llX on lun_id %llX hit max clones already\n", + __func__, to_clone, ba_lun->lun_id); + return -1; + } + + bali->aun_clone_map[to_clone]++; + + return 0; +} + +/** + * ba_space() - returns the amount of free space left in the block allocator + * @ba_lun: Block allocator. + * + * Return: Amount of free space in block allocator + */ +static u64 ba_space(struct ba_lun *ba_lun) +{ + struct ba_lun_info *bali = ba_lun->ba_lun_handle; + + return bali->free_aun_cnt; +} + +/** + * cxlflash_ba_terminate() - frees resources associated with the block allocator + * @ba_lun: Block allocator. + * + * Safe to call in a partially allocated state. + */ +void cxlflash_ba_terminate(struct ba_lun *ba_lun) +{ + struct ba_lun_info *bali = ba_lun->ba_lun_handle; + + if (bali) { + kfree(bali->aun_clone_map); + kfree(bali->lun_alloc_map); + kfree(bali); + ba_lun->ba_lun_handle = NULL; + } +} + +/** + * init_vlun() - initializes a LUN for virtual use + * @lun_info: LUN information structure that owns the block allocator. + * + * Return: 0 on success, -errno on failure + */ +static int init_vlun(struct llun_info *lli) +{ + int rc = 0; + struct glun_info *gli = lli->parent; + struct blka *blka = &gli->blka; + + memset(blka, 0, sizeof(*blka)); + mutex_init(&blka->mutex); + + /* LUN IDs are unique per port, save the index instead */ + blka->ba_lun.lun_id = lli->lun_index; + blka->ba_lun.lsize = gli->max_lba + 1; + blka->ba_lun.lba_size = gli->blk_len; + + blka->ba_lun.au_size = MC_CHUNK_SIZE; + blka->nchunk = blka->ba_lun.lsize / MC_CHUNK_SIZE; + + rc = ba_init(&blka->ba_lun); + if (unlikely(rc)) + pr_debug("%s: cannot init block_alloc, rc=%d\n", __func__, rc); + + pr_debug("%s: returning rc=%d lli=%p\n", __func__, rc, lli); + return rc; +} + +/** + * write_same16() - sends a SCSI WRITE_SAME16 (0) command to specified LUN + * @sdev: SCSI device associated with LUN. + * @lba: Logical block address to start write same. + * @nblks: Number of logical blocks to write same. + * + * Return: 0 on success, -errno on failure + */ +static int write_same16(struct scsi_device *sdev, + u64 lba, + u32 nblks) +{ + u8 *cmd_buf = NULL; + u8 *scsi_cmd = NULL; + u8 *sense_buf = NULL; + int rc = 0; + int result = 0; + int ws_limit = SISLITE_MAX_WS_BLOCKS; + u64 offset = lba; + int left = nblks; + u32 tout = sdev->request_queue->rq_timeout; + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + + cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL); + scsi_cmd = kzalloc(MAX_COMMAND_SIZE, GFP_KERNEL); + sense_buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (unlikely(!cmd_buf || !scsi_cmd || !sense_buf)) { + rc = -ENOMEM; + goto out; + } + + while (left > 0) { + + scsi_cmd[0] = WRITE_SAME_16; + put_unaligned_be64(offset, &scsi_cmd[2]); + put_unaligned_be32(ws_limit < left ? ws_limit : left, + &scsi_cmd[10]); + + result = scsi_execute(sdev, scsi_cmd, DMA_TO_DEVICE, cmd_buf, + CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL); + if (result) { + dev_err_ratelimited(dev, "%s: command failed for " + "offset %lld result=0x%x\n", + __func__, offset, result); + rc = -EIO; + goto out; + } + left -= ws_limit; + offset += ws_limit; + } + +out: + kfree(cmd_buf); + kfree(scsi_cmd); + kfree(sense_buf); + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * grow_lxt() - expands the translation table associated with the specified RHTE + * @afu: AFU associated with the host. + * @sdev: SCSI device associated with LUN. + * @ctxid: Context ID of context owning the RHTE. + * @rhndl: Resource handle associated with the RHTE. + * @rhte: Resource handle entry (RHTE). + * @new_size: Number of translation entries associated with RHTE. + * + * By design, this routine employs a 'best attempt' allocation and will + * truncate the requested size down if there is not sufficient space in + * the block allocator to satisfy the request but there does exist some + * amount of space. The user is made aware of this by returning the size + * allocated. + * + * Return: 0 on success, -errno on failure + */ +static int grow_lxt(struct afu *afu, + struct scsi_device *sdev, + ctx_hndl_t ctxid, + res_hndl_t rhndl, + struct sisl_rht_entry *rhte, + u64 *new_size) +{ + struct sisl_lxt_entry *lxt = NULL, *lxt_old = NULL; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct blka *blka = &gli->blka; + u32 av_size; + u32 ngrps, ngrps_old; + u64 aun; /* chunk# allocated by block allocator */ + u64 delta = *new_size - rhte->lxt_cnt; + u64 my_new_size; + int i, rc = 0; + + /* + * Check what is available in the block allocator before re-allocating + * LXT array. This is done up front under the mutex which must not be + * released until after allocation is complete. + */ + mutex_lock(&blka->mutex); + av_size = ba_space(&blka->ba_lun); + if (unlikely(av_size <= 0)) { + pr_debug("%s: ba_space error: av_size %d\n", __func__, av_size); + mutex_unlock(&blka->mutex); + rc = -ENOSPC; + goto out; + } + + if (av_size < delta) + delta = av_size; + + lxt_old = rhte->lxt_start; + ngrps_old = LXT_NUM_GROUPS(rhte->lxt_cnt); + ngrps = LXT_NUM_GROUPS(rhte->lxt_cnt + delta); + + if (ngrps != ngrps_old) { + /* reallocate to fit new size */ + lxt = kzalloc((sizeof(*lxt) * LXT_GROUP_SIZE * ngrps), + GFP_KERNEL); + if (unlikely(!lxt)) { + mutex_unlock(&blka->mutex); + rc = -ENOMEM; + goto out; + } + + /* copy over all old entries */ + memcpy(lxt, lxt_old, (sizeof(*lxt) * rhte->lxt_cnt)); + } else + lxt = lxt_old; + + /* nothing can fail from now on */ + my_new_size = rhte->lxt_cnt + delta; + + /* add new entries to the end */ + for (i = rhte->lxt_cnt; i < my_new_size; i++) { + /* + * Due to the earlier check of available space, ba_alloc + * cannot fail here. If it did due to internal error, + * leave a rlba_base of -1u which will likely be a + * invalid LUN (too large). + */ + aun = ba_alloc(&blka->ba_lun); + if ((aun == -1ULL) || (aun >= blka->nchunk)) + pr_debug("%s: ba_alloc error: allocated chunk# %llX, " + "max %llX\n", __func__, aun, blka->nchunk - 1); + + /* select both ports, use r/w perms from RHT */ + lxt[i].rlba_base = ((aun << MC_CHUNK_SHIFT) | + (lli->lun_index << LXT_LUNIDX_SHIFT) | + (RHT_PERM_RW << LXT_PERM_SHIFT | + lli->port_sel)); + } + + mutex_unlock(&blka->mutex); + + /* + * The following sequence is prescribed in the SISlite spec + * for syncing up with the AFU when adding LXT entries. + */ + dma_wmb(); /* Make LXT updates are visible */ + + rhte->lxt_start = lxt; + dma_wmb(); /* Make RHT entry's LXT table update visible */ + + rhte->lxt_cnt = my_new_size; + dma_wmb(); /* Make RHT entry's LXT table size update visible */ + + cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC); + + /* free old lxt if reallocated */ + if (lxt != lxt_old) + kfree(lxt_old); + *new_size = my_new_size; +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * shrink_lxt() - reduces translation table associated with the specified RHTE + * @afu: AFU associated with the host. + * @sdev: SCSI device associated with LUN. + * @rhndl: Resource handle associated with the RHTE. + * @rhte: Resource handle entry (RHTE). + * @ctxi: Context owning resources. + * @new_size: Number of translation entries associated with RHTE. + * + * Return: 0 on success, -errno on failure + */ +static int shrink_lxt(struct afu *afu, + struct scsi_device *sdev, + res_hndl_t rhndl, + struct sisl_rht_entry *rhte, + struct ctx_info *ctxi, + u64 *new_size) +{ + struct sisl_lxt_entry *lxt, *lxt_old; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct blka *blka = &gli->blka; + ctx_hndl_t ctxid = DECODE_CTXID(ctxi->ctxid); + bool needs_ws = ctxi->rht_needs_ws[rhndl]; + bool needs_sync = !ctxi->err_recovery_active; + u32 ngrps, ngrps_old; + u64 aun; /* chunk# allocated by block allocator */ + u64 delta = rhte->lxt_cnt - *new_size; + u64 my_new_size; + int i, rc = 0; + + lxt_old = rhte->lxt_start; + ngrps_old = LXT_NUM_GROUPS(rhte->lxt_cnt); + ngrps = LXT_NUM_GROUPS(rhte->lxt_cnt - delta); + + if (ngrps != ngrps_old) { + /* Reallocate to fit new size unless new size is 0 */ + if (ngrps) { + lxt = kzalloc((sizeof(*lxt) * LXT_GROUP_SIZE * ngrps), + GFP_KERNEL); + if (unlikely(!lxt)) { + rc = -ENOMEM; + goto out; + } + + /* Copy over old entries that will remain */ + memcpy(lxt, lxt_old, + (sizeof(*lxt) * (rhte->lxt_cnt - delta))); + } else + lxt = NULL; + } else + lxt = lxt_old; + + /* Nothing can fail from now on */ + my_new_size = rhte->lxt_cnt - delta; + + /* + * The following sequence is prescribed in the SISlite spec + * for syncing up with the AFU when removing LXT entries. + */ + rhte->lxt_cnt = my_new_size; + dma_wmb(); /* Make RHT entry's LXT table size update visible */ + + rhte->lxt_start = lxt; + dma_wmb(); /* Make RHT entry's LXT table update visible */ + + if (needs_sync) + cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC); + + if (needs_ws) { + /* + * Mark the context as unavailable, so that we can release + * the mutex safely. + */ + ctxi->unavail = true; + mutex_unlock(&ctxi->mutex); + } + + /* Free LBAs allocated to freed chunks */ + mutex_lock(&blka->mutex); + for (i = delta - 1; i >= 0; i--) { + /* Mask the higher 48 bits before shifting, even though + * it is a noop + */ + aun = (lxt_old[my_new_size + i].rlba_base & SISL_ASTATUS_MASK); + aun = (aun >> MC_CHUNK_SHIFT); + if (needs_ws) + write_same16(sdev, aun, MC_CHUNK_SIZE); + ba_free(&blka->ba_lun, aun); + } + mutex_unlock(&blka->mutex); + + if (needs_ws) { + /* Make the context visible again */ + mutex_lock(&ctxi->mutex); + ctxi->unavail = false; + } + + /* Free old lxt if reallocated */ + if (lxt != lxt_old) + kfree(lxt_old); + *new_size = my_new_size; +out: + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * _cxlflash_vlun_resize() - changes the size of a virtual lun + * @sdev: SCSI device associated with LUN owning virtual LUN. + * @ctxi: Context owning resources. + * @resize: Resize ioctl data structure. + * + * On successful return, the user is informed of the new size (in blocks) + * of the virtual lun in last LBA format. When the size of the virtual + * lun is zero, the last LBA is reflected as -1. See comment in the + * prologue for _cxlflash_disk_release() regarding AFU syncs and contexts + * on the error recovery list. + * + * Return: 0 on success, -errno on failure + */ +int _cxlflash_vlun_resize(struct scsi_device *sdev, + struct ctx_info *ctxi, + struct dk_cxlflash_resize *resize) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct afu *afu = cfg->afu; + bool put_ctx = false; + + res_hndl_t rhndl = resize->rsrc_handle; + u64 new_size; + u64 nsectors; + u64 ctxid = DECODE_CTXID(resize->context_id), + rctxid = resize->context_id; + + struct sisl_rht_entry *rhte; + + int rc = 0; + + /* + * The requested size (req_size) is always assumed to be in 4k blocks, + * so we have to convert it here from 4k to chunk size. + */ + nsectors = (resize->req_size * CXLFLASH_BLOCK_SIZE) / gli->blk_len; + new_size = DIV_ROUND_UP(nsectors, MC_CHUNK_SIZE); + + pr_debug("%s: ctxid=%llu rhndl=0x%llx, req_size=0x%llx," + "new_size=%llx\n", __func__, ctxid, resize->rsrc_handle, + resize->req_size, new_size); + + if (unlikely(gli->mode != MODE_VIRTUAL)) { + pr_debug("%s: LUN mode does not support resize! (%d)\n", + __func__, gli->mode); + rc = -EINVAL; + goto out; + + } + + if (!ctxi) { + ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); + if (unlikely(!ctxi)) { + pr_debug("%s: Bad context! (%llu)\n", __func__, ctxid); + rc = -EINVAL; + goto out; + } + + put_ctx = true; + } + + rhte = get_rhte(ctxi, rhndl, lli); + if (unlikely(!rhte)) { + pr_debug("%s: Bad resource handle! (%u)\n", __func__, rhndl); + rc = -EINVAL; + goto out; + } + + if (new_size > rhte->lxt_cnt) + rc = grow_lxt(afu, sdev, ctxid, rhndl, rhte, &new_size); + else if (new_size < rhte->lxt_cnt) + rc = shrink_lxt(afu, sdev, rhndl, rhte, ctxi, &new_size); + + resize->hdr.return_flags = 0; + resize->last_lba = (new_size * MC_CHUNK_SIZE * gli->blk_len); + resize->last_lba /= CXLFLASH_BLOCK_SIZE; + resize->last_lba--; + +out: + if (put_ctx) + put_context(ctxi); + pr_debug("%s: resized to %lld returning rc=%d\n", + __func__, resize->last_lba, rc); + return rc; +} + +int cxlflash_vlun_resize(struct scsi_device *sdev, + struct dk_cxlflash_resize *resize) +{ + return _cxlflash_vlun_resize(sdev, NULL, resize); +} + +/** + * cxlflash_restore_luntable() - Restore LUN table to prior state + * @cfg: Internal structure associated with the host. + */ +void cxlflash_restore_luntable(struct cxlflash_cfg *cfg) +{ + struct llun_info *lli, *temp; + u32 chan; + u32 lind; + struct afu *afu = cfg->afu; + struct sisl_global_map *agm = &afu->afu_map->global; + + mutex_lock(&global.mutex); + + list_for_each_entry_safe(lli, temp, &cfg->lluns, list) { + if (!lli->in_table) + continue; + + lind = lli->lun_index; + + if (lli->port_sel == BOTH_PORTS) { + writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); + writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); + pr_debug("%s: Virtual LUN on slot %d id0=%llx, " + "id1=%llx\n", __func__, lind, + lli->lun_id[0], lli->lun_id[1]); + } else { + chan = PORT2CHAN(lli->port_sel); + writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); + pr_debug("%s: Virtual LUN on slot %d chan=%d, " + "id=%llx\n", __func__, lind, chan, + lli->lun_id[chan]); + } + } + + mutex_unlock(&global.mutex); +} + +/** + * init_luntable() - write an entry in the LUN table + * @cfg: Internal structure associated with the host. + * @lli: Per adapter LUN information structure. + * + * On successful return, a LUN table entry is created. + * At the top for LUNs visible on both ports. + * At the bottom for LUNs visible only on one port. + * + * Return: 0 on success, -errno on failure + */ +static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli) +{ + u32 chan; + u32 lind; + int rc = 0; + struct afu *afu = cfg->afu; + struct sisl_global_map *agm = &afu->afu_map->global; + + mutex_lock(&global.mutex); + + if (lli->in_table) + goto out; + + if (lli->port_sel == BOTH_PORTS) { + /* + * If this LUN is visible from both ports, we will put + * it in the top half of the LUN table. + */ + if ((cfg->promote_lun_index == cfg->last_lun_index[0]) || + (cfg->promote_lun_index == cfg->last_lun_index[1])) { + rc = -ENOSPC; + goto out; + } + + lind = lli->lun_index = cfg->promote_lun_index; + writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); + writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); + cfg->promote_lun_index++; + pr_debug("%s: Virtual LUN on slot %d id0=%llx, id1=%llx\n", + __func__, lind, lli->lun_id[0], lli->lun_id[1]); + } else { + /* + * If this LUN is visible only from one port, we will put + * it in the bottom half of the LUN table. + */ + chan = PORT2CHAN(lli->port_sel); + if (cfg->promote_lun_index == cfg->last_lun_index[chan]) { + rc = -ENOSPC; + goto out; + } + + lind = lli->lun_index = cfg->last_lun_index[chan]; + writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); + cfg->last_lun_index[chan]--; + pr_debug("%s: Virtual LUN on slot %d chan=%d, id=%llx\n", + __func__, lind, chan, lli->lun_id[chan]); + } + + lli->in_table = true; +out: + mutex_unlock(&global.mutex); + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; +} + +/** + * cxlflash_disk_virtual_open() - open a virtual disk of specified size + * @sdev: SCSI device associated with LUN owning virtual LUN. + * @arg: UVirtual ioctl data structure. + * + * On successful return, the user is informed of the resource handle + * to be used to identify the virtual lun and the size (in blocks) of + * the virtual lun in last LBA format. When the size of the virtual lun + * is zero, the last LBA is reflected as -1. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct device *dev = &cfg->dev->dev; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + + struct dk_cxlflash_uvirtual *virt = (struct dk_cxlflash_uvirtual *)arg; + struct dk_cxlflash_resize resize; + + u64 ctxid = DECODE_CTXID(virt->context_id), + rctxid = virt->context_id; + u64 lun_size = virt->lun_size; + u64 last_lba = 0; + u64 rsrc_handle = -1; + + int rc = 0; + + struct ctx_info *ctxi = NULL; + struct sisl_rht_entry *rhte = NULL; + + pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); + + mutex_lock(&gli->mutex); + if (gli->mode == MODE_NONE) { + /* Setup the LUN table and block allocator on first call */ + rc = init_luntable(cfg, lli); + if (rc) { + dev_err(dev, "%s: call to init_luntable failed " + "rc=%d!\n", __func__, rc); + goto err0; + } + + rc = init_vlun(lli); + if (rc) { + dev_err(dev, "%s: call to init_vlun failed rc=%d!\n", + __func__, rc); + rc = -ENOMEM; + goto err0; + } + } + + rc = cxlflash_lun_attach(gli, MODE_VIRTUAL, true); + if (unlikely(rc)) { + dev_err(dev, "%s: Failed to attach to LUN! (VIRTUAL)\n", + __func__); + goto err0; + } + mutex_unlock(&gli->mutex); + + ctxi = get_context(cfg, rctxid, lli, 0); + if (unlikely(!ctxi)) { + dev_err(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); + rc = -EINVAL; + goto err1; + } + + rhte = rhte_checkout(ctxi, lli); + if (unlikely(!rhte)) { + dev_err(dev, "%s: too many opens for this context\n", __func__); + rc = -EMFILE; /* too many opens */ + goto err1; + } + + rsrc_handle = (rhte - ctxi->rht_start); + + /* Populate RHT format 0 */ + rhte->nmask = MC_RHT_NMASK; + rhte->fp = SISL_RHT_FP(0U, ctxi->rht_perms); + + /* Resize even if requested size is 0 */ + marshal_virt_to_resize(virt, &resize); + resize.rsrc_handle = rsrc_handle; + rc = _cxlflash_vlun_resize(sdev, ctxi, &resize); + if (rc) { + dev_err(dev, "%s: resize failed rc %d\n", __func__, rc); + goto err2; + } + last_lba = resize.last_lba; + + if (virt->hdr.flags & DK_CXLFLASH_UVIRTUAL_NEED_WRITE_SAME) + ctxi->rht_needs_ws[rsrc_handle] = true; + + virt->hdr.return_flags = 0; + virt->last_lba = last_lba; + virt->rsrc_handle = rsrc_handle; + +out: + if (likely(ctxi)) + put_context(ctxi); + pr_debug("%s: returning handle 0x%llx rc=%d llba %lld\n", + __func__, rsrc_handle, rc, last_lba); + return rc; + +err2: + rhte_checkin(ctxi, rhte); +err1: + cxlflash_lun_detach(gli); + goto out; +err0: + /* Special common cleanup prior to successful LUN attach */ + cxlflash_ba_terminate(&gli->blka.ba_lun); + mutex_unlock(&gli->mutex); + goto out; +} + +/** + * clone_lxt() - copies translation tables from source to destination RHTE + * @afu: AFU associated with the host. + * @blka: Block allocator associated with LUN. + * @ctxid: Context ID of context owning the RHTE. + * @rhndl: Resource handle associated with the RHTE. + * @rhte: Destination resource handle entry (RHTE). + * @rhte_src: Source resource handle entry (RHTE). + * + * Return: 0 on success, -errno on failure + */ +static int clone_lxt(struct afu *afu, + struct blka *blka, + ctx_hndl_t ctxid, + res_hndl_t rhndl, + struct sisl_rht_entry *rhte, + struct sisl_rht_entry *rhte_src) +{ + struct sisl_lxt_entry *lxt; + u32 ngrps; + u64 aun; /* chunk# allocated by block allocator */ + int i, j; + + ngrps = LXT_NUM_GROUPS(rhte_src->lxt_cnt); + + if (ngrps) { + /* allocate new LXTs for clone */ + lxt = kzalloc((sizeof(*lxt) * LXT_GROUP_SIZE * ngrps), + GFP_KERNEL); + if (unlikely(!lxt)) + return -ENOMEM; + + /* copy over */ + memcpy(lxt, rhte_src->lxt_start, + (sizeof(*lxt) * rhte_src->lxt_cnt)); + + /* clone the LBAs in block allocator via ref_cnt */ + mutex_lock(&blka->mutex); + for (i = 0; i < rhte_src->lxt_cnt; i++) { + aun = (lxt[i].rlba_base >> MC_CHUNK_SHIFT); + if (ba_clone(&blka->ba_lun, aun) == -1ULL) { + /* free the clones already made */ + for (j = 0; j < i; j++) { + aun = (lxt[j].rlba_base >> + MC_CHUNK_SHIFT); + ba_free(&blka->ba_lun, aun); + } + + mutex_unlock(&blka->mutex); + kfree(lxt); + return -EIO; + } + } + mutex_unlock(&blka->mutex); + } else { + lxt = NULL; + } + + /* + * The following sequence is prescribed in the SISlite spec + * for syncing up with the AFU when adding LXT entries. + */ + dma_wmb(); /* Make LXT updates are visible */ + + rhte->lxt_start = lxt; + dma_wmb(); /* Make RHT entry's LXT table update visible */ + + rhte->lxt_cnt = rhte_src->lxt_cnt; + dma_wmb(); /* Make RHT entry's LXT table size update visible */ + + cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC); + + pr_debug("%s: returning\n", __func__); + return 0; +} + +/** + * cxlflash_disk_clone() - clone a context by making snapshot of another + * @sdev: SCSI device associated with LUN owning virtual LUN. + * @clone: Clone ioctl data structure. + * + * This routine effectively performs cxlflash_disk_open operation for each + * in-use virtual resource in the source context. Note that the destination + * context must be in pristine state and cannot have any resource handles + * open at the time of the clone. + * + * Return: 0 on success, -errno on failure + */ +int cxlflash_disk_clone(struct scsi_device *sdev, + struct dk_cxlflash_clone *clone) +{ + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; + struct llun_info *lli = sdev->hostdata; + struct glun_info *gli = lli->parent; + struct blka *blka = &gli->blka; + struct afu *afu = cfg->afu; + struct dk_cxlflash_release release = { { 0 }, 0 }; + + struct ctx_info *ctxi_src = NULL, + *ctxi_dst = NULL; + struct lun_access *lun_access_src, *lun_access_dst; + u32 perms; + u64 ctxid_src = DECODE_CTXID(clone->context_id_src), + ctxid_dst = DECODE_CTXID(clone->context_id_dst), + rctxid_src = clone->context_id_src, + rctxid_dst = clone->context_id_dst; + int adap_fd_src = clone->adap_fd_src; + int i, j; + int rc = 0; + bool found; + LIST_HEAD(sidecar); + + pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu adap_fd_src=%d\n", + __func__, ctxid_src, ctxid_dst, adap_fd_src); + + /* Do not clone yourself */ + if (unlikely(rctxid_src == rctxid_dst)) { + rc = -EINVAL; + goto out; + } + + if (unlikely(gli->mode != MODE_VIRTUAL)) { + rc = -EINVAL; + pr_debug("%s: Clone not supported on physical LUNs! (%d)\n", + __func__, gli->mode); + goto out; + } + + ctxi_src = get_context(cfg, rctxid_src, lli, CTX_CTRL_CLONE); + ctxi_dst = get_context(cfg, rctxid_dst, lli, 0); + if (unlikely(!ctxi_src || !ctxi_dst)) { + pr_debug("%s: Bad context! (%llu,%llu)\n", __func__, + ctxid_src, ctxid_dst); + rc = -EINVAL; + goto out; + } + + if (unlikely(adap_fd_src != ctxi_src->lfd)) { + pr_debug("%s: Invalid source adapter fd! (%d)\n", + __func__, adap_fd_src); + rc = -EINVAL; + goto out; + } + + /* Verify there is no open resource handle in the destination context */ + for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) + if (ctxi_dst->rht_start[i].nmask != 0) { + rc = -EINVAL; + goto out; + } + + /* Clone LUN access list */ + list_for_each_entry(lun_access_src, &ctxi_src->luns, list) { + found = false; + list_for_each_entry(lun_access_dst, &ctxi_dst->luns, list) + if (lun_access_dst->sdev == lun_access_src->sdev) { + found = true; + break; + } + + if (!found) { + lun_access_dst = kzalloc(sizeof(*lun_access_dst), + GFP_KERNEL); + if (unlikely(!lun_access_dst)) { + pr_err("%s: Unable to allocate lun_access!\n", + __func__); + rc = -ENOMEM; + goto out; + } + + *lun_access_dst = *lun_access_src; + list_add(&lun_access_dst->list, &sidecar); + } + } + + if (unlikely(!ctxi_src->rht_out)) { + pr_debug("%s: Nothing to clone!\n", __func__); + goto out_success; + } + + /* User specified permission on attach */ + perms = ctxi_dst->rht_perms; + + /* + * Copy over checked-out RHT (and their associated LXT) entries by + * hand, stopping after we've copied all outstanding entries and + * cleaning up if the clone fails. + * + * Note: This loop is equivalent to performing cxlflash_disk_open and + * cxlflash_vlun_resize. As such, LUN accounting needs to be taken into + * account by attaching after each successful RHT entry clone. In the + * event that a clone failure is experienced, the LUN detach is handled + * via the cleanup performed by _cxlflash_disk_release. + */ + for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) { + if (ctxi_src->rht_out == ctxi_dst->rht_out) + break; + if (ctxi_src->rht_start[i].nmask == 0) + continue; + + /* Consume a destination RHT entry */ + ctxi_dst->rht_out++; + ctxi_dst->rht_start[i].nmask = ctxi_src->rht_start[i].nmask; + ctxi_dst->rht_start[i].fp = + SISL_RHT_FP_CLONE(ctxi_src->rht_start[i].fp, perms); + ctxi_dst->rht_lun[i] = ctxi_src->rht_lun[i]; + + rc = clone_lxt(afu, blka, ctxid_dst, i, + &ctxi_dst->rht_start[i], + &ctxi_src->rht_start[i]); + if (rc) { + marshal_clone_to_rele(clone, &release); + for (j = 0; j < i; j++) { + release.rsrc_handle = j; + _cxlflash_disk_release(sdev, ctxi_dst, + &release); + } + + /* Put back the one we failed on */ + rhte_checkin(ctxi_dst, &ctxi_dst->rht_start[i]); + goto err; + } + + cxlflash_lun_attach(gli, gli->mode, false); + } + +out_success: + list_splice(&sidecar, &ctxi_dst->luns); + sys_close(adap_fd_src); + + /* fall through */ +out: + if (ctxi_src) + put_context(ctxi_src); + if (ctxi_dst) + put_context(ctxi_dst); + pr_debug("%s: returning rc=%d\n", __func__, rc); + return rc; + +err: + list_for_each_entry_safe(lun_access_src, lun_access_dst, &sidecar, list) + kfree(lun_access_src); + goto out; +} diff --git a/drivers/scsi/cxlflash/vlun.h b/drivers/scsi/cxlflash/vlun.h new file mode 100644 index 000000000000..8b29a74946e4 --- /dev/null +++ b/drivers/scsi/cxlflash/vlun.h @@ -0,0 +1,86 @@ +/* + * CXL Flash Device Driver + * + * Written by: Manoj N. Kumar , IBM Corporation + * Matthew R. Ochs , IBM Corporation + * + * Copyright (C) 2015 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _CXLFLASH_VLUN_H +#define _CXLFLASH_VLUN_H + +/* RHT - Resource Handle Table */ +#define MC_RHT_NMASK 16 /* in bits */ +#define MC_CHUNK_SHIFT MC_RHT_NMASK /* shift to go from LBA to chunk# */ + +#define HIBIT (BITS_PER_LONG - 1) + +#define MAX_AUN_CLONE_CNT 0xFF + +/* + * LXT - LBA Translation Table + * + * +-------+-------+-------+-------+-------+-------+-------+---+---+ + * | RLBA_BASE |LUN_IDX| P |SEL| + * +-------+-------+-------+-------+-------+-------+-------+---+---+ + * + * The LXT Entry contains the physical LBA where the chunk starts (RLBA_BASE). + * AFU ORes the low order bits from the virtual LBA (offset into the chunk) + * with RLBA_BASE. The result is the physical LBA to be sent to storage. + * The LXT Entry also contains an index to a LUN TBL and a bitmask of which + * outgoing (FC) * ports can be selected. The port select bit-mask is ANDed + * with a global port select bit-mask maintained by the driver. + * In addition, it has permission bits that are ANDed with the + * RHT permissions to arrive at the final permissions for the chunk. + * + * LXT tables are allocated dynamically in groups. This is done to avoid + * a malloc/free overhead each time the LXT has to grow or shrink. + * + * Based on the current lxt_cnt (used), it is always possible to know + * how many are allocated (used+free). The number of allocated entries is + * not stored anywhere. + * + * The LXT table is re-allocated whenever it needs to cross into another group. +*/ +#define LXT_GROUP_SIZE 8 +#define LXT_NUM_GROUPS(lxt_cnt) (((lxt_cnt) + 7)/8) /* alloc'ed groups */ +#define LXT_LUNIDX_SHIFT 8 /* LXT entry, shift for LUN index */ +#define LXT_PERM_SHIFT 4 /* LXT entry, shift for permission bits */ + +struct ba_lun_info { + u64 *lun_alloc_map; + u32 lun_bmap_size; + u32 total_aus; + u64 free_aun_cnt; + + /* indices to be used for elevator lookup of free map */ + u32 free_low_idx; + u32 free_curr_idx; + u32 free_high_idx; + + u8 *aun_clone_map; +}; + +struct ba_lun { + u64 lun_id; + u64 wwpn; + size_t lsize; /* LUN size in number of LBAs */ + size_t lba_size; /* LBA size in number of bytes */ + size_t au_size; /* Allocation Unit size in number of LBAs */ + struct ba_lun_info *ba_lun_handle; +}; + +/* Block Allocator */ +struct blka { + struct ba_lun ba_lun; + u64 nchunk; /* number of chunks */ + struct mutex mutex; +}; + +#endif /* ifndef _CXLFLASH_SUPERPIPE_H */ diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h index 570773406531..831351b2e660 100644 --- a/include/uapi/scsi/cxlflash_ioctl.h +++ b/include/uapi/scsi/cxlflash_ioctl.h @@ -71,6 +71,17 @@ struct dk_cxlflash_udirect { __u64 reserved[8]; /* Reserved for future use */ }; +#define DK_CXLFLASH_UVIRTUAL_NEED_WRITE_SAME 0x8000000000000000ULL + +struct dk_cxlflash_uvirtual { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context to own virtual resources */ + __u64 lun_size; /* Requested size, in 4K blocks */ + __u64 rsrc_handle; /* Returned resource handle */ + __u64 last_lba; /* Returned last LBA of LUN */ + __u64 reserved[8]; /* Reserved for future use */ +}; + struct dk_cxlflash_release { struct dk_cxlflash_hdr hdr; /* Common fields */ __u64 context_id; /* Context owning resources */ @@ -78,6 +89,23 @@ struct dk_cxlflash_release { __u64 reserved[8]; /* Reserved for future use */ }; +struct dk_cxlflash_resize { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id; /* Context owning resources */ + __u64 rsrc_handle; /* Resource handle of LUN to resize */ + __u64 req_size; /* New requested size, in 4K blocks */ + __u64 last_lba; /* Returned last LBA of LUN */ + __u64 reserved[8]; /* Reserved for future use */ +}; + +struct dk_cxlflash_clone { + struct dk_cxlflash_hdr hdr; /* Common fields */ + __u64 context_id_src; /* Context to clone from */ + __u64 context_id_dst; /* Context to clone to */ + __u64 adap_fd_src; /* Source context adapter fd */ + __u64 reserved[8]; /* Reserved for future use */ +}; + #define DK_CXLFLASH_VERIFY_SENSE_LEN 18 #define DK_CXLFLASH_VERIFY_HINT_SENSE 0x8000000000000000ULL @@ -118,7 +146,10 @@ union cxlflash_ioctls { struct dk_cxlflash_attach attach; struct dk_cxlflash_detach detach; struct dk_cxlflash_udirect udirect; + struct dk_cxlflash_uvirtual uvirtual; struct dk_cxlflash_release release; + struct dk_cxlflash_resize resize; + struct dk_cxlflash_clone clone; struct dk_cxlflash_verify verify; struct dk_cxlflash_recover_afu recover_afu; struct dk_cxlflash_manage_lun manage_lun; @@ -136,5 +167,8 @@ union cxlflash_ioctls { #define DK_CXLFLASH_VERIFY CXL_IOWR(0x84, dk_cxlflash_verify) #define DK_CXLFLASH_RECOVER_AFU CXL_IOWR(0x85, dk_cxlflash_recover_afu) #define DK_CXLFLASH_MANAGE_LUN CXL_IOWR(0x86, dk_cxlflash_manage_lun) +#define DK_CXLFLASH_USER_VIRTUAL CXL_IOWR(0x87, dk_cxlflash_uvirtual) +#define DK_CXLFLASH_VLUN_RESIZE CXL_IOWR(0x88, dk_cxlflash_resize) +#define DK_CXLFLASH_VLUN_CLONE CXL_IOWR(0x89, dk_cxlflash_clone) #endif /* ifndef _CXLFLASH_IOCTL_H */ From 46c6d45d7875a0328258a574e376ae75f7b2a64b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Aug 2015 23:35:25 +0300 Subject: [PATCH 75/85] cxlflash: off by one bug in cxlflash_show_port_status() The > should be >= or we read one element past the end of the array. Fixes: c21e0bbfc485 ('cxlflash: Base support for IBM CXL Flash Adapter') Signed-off-by: Dan Carpenter Acked-by: Matthew R. Ochs Signed-off-by: James Bottomley --- drivers/scsi/cxlflash/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 458ed838f83a..fde2ba9342dc 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -586,7 +586,7 @@ static ssize_t cxlflash_show_port_status(struct device *dev, u64 *fc_regs; rc = kstrtouint((attr->attr.name + 4), 10, &port); - if (rc || (port > NUM_FC_PORTS)) + if (rc || (port >= NUM_FC_PORTS)) return 0; fc_regs = &afu->afu_map->global.fc_regs[port][0]; From 4da74db0d9a6ffe053d3a3efa756906e0afc4cf7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Aug 2015 11:57:43 +0300 Subject: [PATCH 76/85] cxlflash: shift wrapping bug in afu_link_reset() "port_sel" is a u64 so the shifting should also be a 64 bit shift. Fixes: c21e0bbfc485 ('cxlflash: Base support for IBM CXL Flash Adapter') Signed-off-by: Dan Carpenter Reviewed-by: Johannes Thumshirn Acked-by: Matthew R. Ochs Signed-off-by: James Bottomley --- drivers/scsi/cxlflash/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index fde2ba9342dc..caa1d09dafec 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -1248,7 +1248,7 @@ static void afu_link_reset(struct afu *afu, int port, u64 *fc_regs) /* first switch the AFU to the other links, if any */ port_sel = readq_be(&afu->afu_map->global.regs.afu_port_sel); - port_sel &= ~(1 << port); + port_sel &= ~(1ULL << port); writeq_be(port_sel, &afu->afu_map->global.regs.afu_port_sel); cxlflash_afu_sync(afu, 0, 0, AFU_GSYNC); @@ -1265,7 +1265,7 @@ static void afu_link_reset(struct afu *afu, int port, u64 *fc_regs) __func__, port); /* switch back to include this port */ - port_sel |= (1 << port); + port_sel |= (1ULL << port); writeq_be(port_sel, &afu->afu_map->global.regs.afu_port_sel); cxlflash_afu_sync(afu, 0, 0, AFU_GSYNC); From 89576205de8a5b6c19a4b3bb25bd16484a567b4e Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Wed, 26 Aug 2015 18:36:12 -0500 Subject: [PATCH 77/85] cxlflash: Remove unused variable from queuecommand The queuecommand routine has a local dev pointer used for the dev_* prints. The two prints that currently exist are tucked under a debug define and thus can be left out. Use the actual location instead of a local to avoid this warning. This patch is intended to be applied after the "CXL Flash Error Recovery and Superpipe" series. Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reported-by: kbuild test robot Signed-off-by: James Bottomley --- drivers/scsi/cxlflash/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index caa1d09dafec..3e3ccf16e7c2 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -354,7 +354,6 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; struct afu *afu = cfg->afu; struct pci_dev *pdev = cfg->dev; - struct device *dev = &cfg->dev->dev; struct afu_cmd *cmd; u32 port_sel = scp->device->channel + 1; int nseg, i, ncount; @@ -384,11 +383,13 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) switch (cfg->state) { case STATE_LIMBO: - dev_dbg_ratelimited(dev, "%s: device in limbo!\n", __func__); + dev_dbg_ratelimited(&cfg->dev->dev, "%s: device in limbo!\n", + __func__); rc = SCSI_MLQUEUE_HOST_BUSY; goto out; case STATE_FAILTERM: - dev_dbg_ratelimited(dev, "%s: device has failed!\n", __func__); + dev_dbg_ratelimited(&cfg->dev->dev, "%s: device has failed!\n", + __func__); scp->result = (DID_NO_CONNECT << 16); scp->scsi_done(scp); rc = 0; From 6ee5c61535a2df807069145970d3e7fa492a3fac Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:46 -0700 Subject: [PATCH 78/85] storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges. Rather than look for sets of specific protocol versions, make decisions based on ranges. This will be safer and require fewer changes going forward as we add more storage protocol versions. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index dbc9d9a1c89d..05f6f970826e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -981,8 +981,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if ((vmbus_proto_version != VERSION_WIN7) && - (vmbus_proto_version != VERSION_WS2008)) { + if (vmbus_proto_version >= VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1759,9 +1758,7 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - switch (vmbus_proto_version) { - case VERSION_WS2008: - case VERSION_WIN7: + if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; @@ -1769,8 +1766,7 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; - break; - default: + } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; vmstor_current_major = VMSTOR_WIN8_MAJOR; @@ -1784,7 +1780,6 @@ static int storvsc_probe(struct hv_device *device, * VCPUs in the guest. */ max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); - break; } scsi_driver.can_queue = (max_outstanding_req_per_channel * From 2492fd7a60270b81b7ed491745fd595a26841a45 Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:47 -0700 Subject: [PATCH 79/85] storvsc: Use a single value to track protocol versions Use a single value to track protocol versions to simplify comparisons and to be consistent with vmbus version tracking. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 05f6f970826e..367f66cc1f07 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -58,12 +58,11 @@ * Win8: 5.1 */ +#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff))) -#define VMSTOR_WIN7_MAJOR 4 -#define VMSTOR_WIN7_MINOR 2 - -#define VMSTOR_WIN8_MAJOR 5 -#define VMSTOR_WIN8_MINOR 1 +#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) +#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) /* Packet structure describing virtual storage requests. */ @@ -161,8 +160,7 @@ static int sense_buffer_size; */ static int vmscsi_size_delta; -static int vmstor_current_major; -static int vmstor_current_minor; +static int vmstor_proto_version; struct vmscsi_win8_extension { /* @@ -474,18 +472,6 @@ done: kfree(wrk); } -/* - * Major/minor macros. Minor version is in LSB, meaning that earlier flat - * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). - */ - -static inline u16 storvsc_get_version(u8 major, u8 minor) -{ - u16 version; - - version = ((major << 8) | minor); - return version; -} /* * We can get incoming messages from the host that are not in response to @@ -923,8 +909,7 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = - storvsc_get_version(vmstor_current_major, vmstor_current_minor); + vstor_packet->version.major_minor = vmstor_proto_version; /* * The revision number is only used in Windows; set it to 0. @@ -1555,7 +1540,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) u32 payload_sz; u32 length; - if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + if (vmstor_proto_version <= VMSTOR_PROTO_VERSION_WIN8) { /* * On legacy hosts filter unimplemented commands. * Future hosts are expected to correctly handle @@ -1761,16 +1746,14 @@ static int storvsc_probe(struct hv_device *device, if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); - vmstor_current_major = VMSTOR_WIN7_MAJOR; - vmstor_current_minor = VMSTOR_WIN7_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; From 1a3631081d88180f5cc421711e40b4aecff8618e Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:48 -0700 Subject: [PATCH 80/85] storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation. Currently we are making decisions based on vmbus protocol versions that have been negotiated; use storage potocol versions instead. [jejb: fold ARRAY_SIZE conversion suggested by Johannes Thumshirn make vmstor_protocol static] Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 108 +++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 367f66cc1f07..d6a42c000048 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -56,14 +56,18 @@ * V1 RC > 2008/1/31: 2.0 * Win7: 4.2 * Win8: 5.1 + * Win8.1: 6.0 + * Win10: 6.2 */ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) +#define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) - +#define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0) +#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) /* Packet structure describing virtual storage requests. */ enum vstor_packet_operation { @@ -204,6 +208,45 @@ struct vmscsi_request { } __attribute((packed)); +/* + * The list of storage protocols in order of preference. + */ +struct vmstor_protocol { + int protocol_version; + int sense_buffer_size; + int vmscsi_size_delta; +}; + + +static const struct vmstor_protocol vmstor_protocols[] = { + { + VMSTOR_PROTO_VERSION_WIN10, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8_1, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN7, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + }, + { + VMSTOR_PROTO_VERSION_WIN6, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + } +}; + + /* * This structure is sent during the intialization phase to get the different * properties of the channel. @@ -864,7 +907,7 @@ static int storvsc_channel_init(struct hv_device *device) struct storvsc_device *stor_device; struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t; + int ret, t, i; int max_chns; bool process_sub_channels = false; @@ -904,36 +947,59 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; - /* reuse the packet for version range supported */ - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; + for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { + /* reuse the packet for version range supported */ + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = + VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = vmstor_proto_version; + vstor_packet->version.major_minor = + vmstor_protocols[i].protocol_version; - /* - * The revision number is only used in Windows; set it to 0. - */ - vstor_packet->version.revision = 0; + /* + * The revision number is only used in Windows; set it to 0. + */ + vstor_packet->version.revision = 0; - ret = vmbus_sendpacket(device->channel, vstor_packet, + ret = vmbus_sendpacket(device->channel, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; + if (ret != 0) + goto cleanup; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) { + ret = -EINVAL; + goto cleanup; + } + + if (vstor_packet->status == 0) { + vmstor_proto_version = + vmstor_protocols[i].protocol_version; + + sense_buffer_size = + vmstor_protocols[i].sense_buffer_size; + + vmscsi_size_delta = + vmstor_protocols[i].vmscsi_size_delta; + + break; + } } - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + if (vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -1746,14 +1812,12 @@ static int storvsc_probe(struct hv_device *device, if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); - vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; - vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; From cb11feada9c049bc633831d3a5dcc50163f13b5e Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:49 -0700 Subject: [PATCH 81/85] storvsc: use correct defaults for values determined by protocol negotiation Use correct defaults for values determined by protocol negotiation, instead of resetting them with every scsi controller. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d6a42c000048..8937ce92f875 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -151,19 +151,17 @@ struct hv_fc_wwn_packet { /* * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. + * variable to track the size we should use. This value will + * likely change during protocol negotiation but it is valid + * to start by assuming pre-Win8. */ -static int sense_buffer_size; +static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. - */ - -static int vmscsi_size_delta; + * The storage protocol version is determined during the + * initial exchange with the host. It will indicate which + * storage functionality is available in the host. +*/ static int vmstor_proto_version; struct vmscsi_win8_extension { @@ -208,6 +206,17 @@ struct vmscsi_request { } __attribute((packed)); +/* + * The size of the vmscsi_request has changed in win8. The + * additional size is because of new elements added to the + * structure. These elements are valid only when we are talking + * to a win8 host. + * Track the correction to size we need to apply. This value + * will likely change during protocol negotiation but it is + * valid to start by assuming pre-Win8. + */ +static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + /* * The list of storage protocols in order of preference. */ @@ -1810,14 +1819,10 @@ static int storvsc_probe(struct hv_device *device, */ if (vmbus_proto_version < VERSION_WIN8) { - sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; From e6c4bc66842752110a66746e2d044fafc01e4800 Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:50 -0700 Subject: [PATCH 82/85] storvsc: use storage protocol version to determine storage capabilities Use storage protocol version instead of vmbus protocol version when determining storage capabilities. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 8937ce92f875..97219a0bb280 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1041,7 +1041,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if (vmbus_proto_version >= VERSION_WIN8) { + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1483,9 +1483,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) * if the device is a MSFT virtual device. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { - switch (vmbus_proto_version) { - case VERSION_WIN8: - case VERSION_WIN8_1: + switch (vmstor_proto_version) { + case VMSTOR_PROTO_VERSION_WIN8: + case VMSTOR_PROTO_VERSION_WIN8_1: sdevice->scsi_level = SCSI_SPC_3; break; } From b95f5be09069526cf53705acbc1e22600f3f550b Mon Sep 17 00:00:00 2001 From: Keith Mange Date: Thu, 13 Aug 2015 08:43:51 -0700 Subject: [PATCH 83/85] storvsc: Allow write_same when host is windows 10 Allow WRITE_SAME for Windows10 and above hosts. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 97219a0bb280..cbb1bd1e020c 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1480,7 +1480,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice) /* * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 - * if the device is a MSFT virtual device. + * if the device is a MSFT virtual device. If the host is + * WIN10 or newer, allow write_same. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { switch (vmstor_proto_version) { @@ -1489,6 +1490,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->scsi_level = SCSI_SPC_3; break; } + + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN10) + sdevice->no_write_same = 0; } return 0; From 111f2d15b543e15c1e0ee89745fae84e3eb91932 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 13 Aug 2015 08:43:52 -0700 Subject: [PATCH 84/85] storvsc: Set the error code correctly in failure conditions In the function storvsc_channel_init(), error code was not getting set correctly in some of the failure cases. Fix this issue. Signed-off-by: K. Y. Srinivasan Reported-by: Dan Carpenter Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index cbb1bd1e020c..40c43aeb4ff3 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -952,8 +952,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { @@ -1032,8 +1034,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } /* * Check to see if multi-channel support is there. @@ -1070,8 +1074,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } if (process_sub_channels) handle_multichannel_storage(device, max_chns); From 9f55bca2b82a77a3cc3204900db2fc40ab30019e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Aug 2015 12:20:29 +0300 Subject: [PATCH 85/85] aic94xx: set an error code on failure We recently did some cleanup here and now the static checkers notice that there is a missing error code when ioremap() fails. Let's set it to -ENOMEM. Signed-off-by: Dan Carpenter Reviewed-by: Johannes Thumshirn Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 4b135cca42a1..31e8576cbaab 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -109,6 +109,7 @@ static int asd_map_memio(struct asd_ha_struct *asd_ha) if (!io_handle->addr) { asd_printk("couldn't map MBAR%d of %s\n", i==0?0:1, pci_name(asd_ha->pcidev)); + err = -ENOMEM; goto Err_unreq; } }