Merge patch series "smartpqi: fixes and updates for 2.1.42-011"

David Strahan <david.strahan@microchip.com> says:

These patches are based on Martin Petersen's 7.2/scsi-queue tree
https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
 7.2/scsi-queue

This patch series includes four patches, with two main functional changes:

1. smartpqi-Fix-AIO-retry-marker-cleared-by-SCSI-core-between-dispatches

   On recent Linux kernels the driver can enter a retry loop on the
   AIO fast path when a request is retried, looping until timeout, and
   a diagnostic path that takes a physical drive offline on AIO-bypass
   failure is never entered.

   Registers a per-command initialization callback with the SCSI core
   so its presence causes the core to skip the per-dispatch clear of
   the retry marker, letting it survive the requeue so the AIO-to-RAID
   fallback proceeds as intended.

2. smartpqi-add-support-for-CCISS_BIG_PASSTHRU-ioctl

   Adds pqi_big_passthru_ioctl() to handle CCISS_BIG_PASSTHRU ioctl
   requests. The existing passthru ioctl uses a 16-bit integer for the
   I/O buffer size, limiting transfers to 64KB. The big passthru ioctl
   uses BIG_IOCTL_Command_struct, which stores the buffer size as a
   32-bit integer, allowing the larger transfers required by some
   management utilities.

The other two patches:
3. smartpqi-add-new-pci-device-ids
   Adds PCI IDs for new Hurray Data, ZTE, and Ramaxel controllers.
   No functional changes.
4. smartpqi-update-driver-version-to-2.1.42-011
   Updates the driver version string.
   No functional changes.

Link: https://patch.msgid.link/20260722220401.6357-1-david.strahan@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen
2026-07-28 21:58:00 -04:00
2 changed files with 202 additions and 3 deletions

View File

@@ -34,11 +34,11 @@
#define BUILD_TIMESTAMP
#endif
#define DRIVER_VERSION "2.1.36-026"
#define DRIVER_VERSION "2.1.42-011"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 1
#define DRIVER_RELEASE 36
#define DRIVER_REVISION 26
#define DRIVER_RELEASE 42
#define DRIVER_REVISION 11
#define DRIVER_NAME "Microchip SmartPQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
@@ -66,6 +66,12 @@ static struct pqi_cmd_priv *pqi_cmd_priv(struct scsi_cmnd *cmd)
return scsi_cmd_priv(cmd);
}
static int pqi_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
{
memset(pqi_cmd_priv(cmd), 0, sizeof(struct pqi_cmd_priv));
return 0;
}
static void pqi_verify_structures(void);
static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info,
enum pqi_ctrl_shutdown_reason ctrl_shutdown_reason);
@@ -5958,6 +5964,17 @@ void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd)
struct pqi_scsi_dev *device;
struct completion *wait;
/*
* Clear the AIO-retry marker on final completion so the tag
* starts clean on its next dispatch. On DID_IMM_RETRY leave
* it intact: pqi_aio_io_complete() sets DID_IMM_RETRY and
* bumps the marker to steer the requeue onto the RAID path,
* and pqi_process_raid_io_error() consumes the non-zero
* marker to offline a misbehaving drive.
*/
if (host_byte(scmd->result) != DID_IMM_RETRY)
pqi_cmd_priv(scmd)->this_residual = 0;
if (!scmd->device) {
set_host_byte(scmd, DID_NO_CONNECT);
return;
@@ -6918,6 +6935,144 @@ static int pqi_passthru_ioctl(struct pqi_ctrl_info *ctrl_info, void __user *arg)
return rc;
}
static int pqi_big_passthru_ioctl(struct pqi_ctrl_info *ctrl_info, void __user *arg)
{
int rc;
char *kernel_buffer = NULL;
u16 iu_length;
size_t sense_data_length;
BIG_IOCTL_Command_struct iocommand;
struct pqi_raid_path_request request;
struct pqi_raid_error_info pqi_error_info;
struct ciss_error_info ciss_error_info;
if (pqi_ctrl_offline(ctrl_info))
return -ENXIO;
if (pqi_ofa_in_progress(ctrl_info) && pqi_ctrl_blocked(ctrl_info))
return -EBUSY;
if (!arg)
return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
if (copy_from_user(&iocommand, arg, sizeof(iocommand)))
return -EFAULT;
if (iocommand.buf_size < 1 &&
iocommand.Request.Type.Direction != XFER_NONE)
return -EINVAL;
if (iocommand.Request.CDBLen > sizeof(request.cdb))
return -EINVAL;
if (iocommand.Request.Type.Type != TYPE_CMD)
return -EINVAL;
switch (iocommand.Request.Type.Direction) {
case XFER_NONE:
case XFER_WRITE:
case XFER_READ:
case XFER_READ | XFER_WRITE:
break;
default:
return -EINVAL;
}
if (iocommand.buf_size > 0) {
kernel_buffer = kmalloc(iocommand.buf_size, GFP_KERNEL);
if (!kernel_buffer)
return -ENOMEM;
if (iocommand.Request.Type.Direction & XFER_WRITE) {
if (copy_from_user(kernel_buffer, iocommand.buf,
iocommand.buf_size)) {
rc = -EFAULT;
goto out;
}
} else {
memset(kernel_buffer, 0, iocommand.buf_size);
}
}
memset(&request, 0, sizeof(request));
request.header.iu_type = PQI_REQUEST_IU_RAID_PATH_IO;
iu_length = offsetof(struct pqi_raid_path_request, sg_descriptors) -
PQI_REQUEST_HEADER_LENGTH;
memcpy(request.lun_number, iocommand.LUN_info.LunAddrBytes, sizeof(request.lun_number));
memcpy(request.cdb, iocommand.Request.CDB, iocommand.Request.CDBLen);
request.additional_cdb_bytes_usage = SOP_ADDITIONAL_CDB_BYTES_0;
switch (iocommand.Request.Type.Direction) {
case XFER_NONE:
request.data_direction = SOP_NO_DIRECTION_FLAG;
break;
case XFER_WRITE:
request.data_direction = SOP_WRITE_FLAG;
break;
case XFER_READ:
request.data_direction = SOP_READ_FLAG;
break;
case XFER_READ | XFER_WRITE:
request.data_direction = SOP_BIDIRECTIONAL;
break;
}
request.task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE;
if (iocommand.buf_size > 0) {
put_unaligned_le32(iocommand.buf_size, &request.buffer_length);
rc = pqi_map_single(ctrl_info->pci_dev,
&request.sg_descriptors[0], kernel_buffer,
iocommand.buf_size, DMA_BIDIRECTIONAL);
if (rc)
goto out;
iu_length += sizeof(request.sg_descriptors[0]);
}
put_unaligned_le16(iu_length, &request.header.iu_length);
if (ctrl_info->raid_iu_timeout_supported)
put_unaligned_le32(iocommand.Request.Timeout, &request.timeout);
rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header,
PQI_SYNC_FLAGS_INTERRUPTABLE, &pqi_error_info);
if (iocommand.buf_size > 0)
pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1, DMA_BIDIRECTIONAL);
memset(&iocommand.error_info, 0, sizeof(iocommand.error_info));
if (rc == 0) {
pqi_error_info_to_ciss(&pqi_error_info, &ciss_error_info);
iocommand.error_info.ScsiStatus = ciss_error_info.scsi_status;
iocommand.error_info.CommandStatus = ciss_error_info.command_status;
sense_data_length = ciss_error_info.sense_data_length;
if (sense_data_length) {
if (sense_data_length > sizeof(iocommand.error_info.SenseInfo))
sense_data_length = sizeof(iocommand.error_info.SenseInfo);
memcpy(iocommand.error_info.SenseInfo,
pqi_error_info.data, sense_data_length);
iocommand.error_info.SenseLen = sense_data_length;
}
}
if (copy_to_user(arg, &iocommand, sizeof(iocommand))) {
rc = -EFAULT;
goto out;
}
if (rc == 0 && iocommand.buf_size > 0 &&
(iocommand.Request.Type.Direction & XFER_READ)) {
if (copy_to_user(iocommand.buf, kernel_buffer,
iocommand.buf_size)) {
rc = -EFAULT;
}
}
out:
kfree(kernel_buffer);
return rc;
}
static int pqi_ioctl(struct scsi_device *sdev, unsigned int cmd,
void __user *arg)
{
@@ -6941,6 +7096,12 @@ static int pqi_ioctl(struct scsi_device *sdev, unsigned int cmd,
case CCISS_PASSTHRU:
rc = pqi_passthru_ioctl(ctrl_info, arg);
break;
case CCISS_BIG_PASSTHRU:
rc = pqi_big_passthru_ioctl(ctrl_info, arg);
break;
case CCISS_BIG_PASSTHRU_SUPPORTED:
rc = 0;
break;
default:
rc = -EINVAL;
break;
@@ -7612,6 +7773,7 @@ static const struct scsi_host_template pqi_driver_template = {
.sdev_groups = pqi_sdev_groups,
.shost_groups = pqi_shost_groups,
.cmd_size = sizeof(struct pqi_cmd_priv),
.init_cmd_priv = pqi_init_cmd_priv,
};
static int pqi_register_scsi(struct pqi_ctrl_info *ctrl_info)
@@ -10152,10 +10314,30 @@ static const struct pci_device_id pqi_pci_id_table[] = {
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4240)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4246)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4256)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4356)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4840)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4940)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4a46)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_VENDOR_ID_ADVANTECH, 0x8312)
@@ -10340,6 +10522,18 @@ static const struct pci_device_id pqi_pci_id_table[] = {
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x544f)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x5451)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x5452)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x5453)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x54da)
@@ -10380,6 +10574,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1f3f, 0x0610)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1f3f, 0x0670)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_VENDOR_ID_LENOVO, 0x0220)

View File

@@ -85,5 +85,6 @@ typedef struct _LogvolInfo_struct{
#define CCISS_RESCANDISK _IO(CCISS_IOC_MAGIC, 16)
#define CCISS_GETLUNINFO _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct)
#define CCISS_BIG_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL_Command_struct)
#define CCISS_BIG_PASSTHRU_SUPPORTED _IO(CCISS_IOC_MAGIC, 19)
#endif /* _UAPICCISS_IOCTLH */