diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index fe943ce76c60..5fa6655aee84 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -1532,3 +1532,30 @@ Contact: Bean Huo Description: rtc_update_ms indicates how often the host should synchronize or update the UFS RTC. If set to 0, this will disable UFS RTC periodic update. + +What: /sys/devices/platform/.../ufshci_capabilities/version +Date: August 2024 +Contact: Avri Altman +Description: + Host Capabilities register group: UFS version register. + Symbol - VER. This file shows the UFSHCD version. + Example: Version 3.12 would be represented as 0000_0312h. + The file is read only. + +What: /sys/devices/platform/.../ufshci_capabilities/product_id +Date: August 2024 +Contact: Avri Altman +Description: + Host Capabilities register group: product ID register. + Symbol - HCPID. This file shows the UFSHCD product id. + The content of this register is vendor specific. + The file is read only. + +What: /sys/devices/platform/.../ufshci_capabilities/man_id +Date: August 2024 +Contact: Avri Altman +Description: + Host Capabilities register group: manufacturer ID register. + Symbol - HCMID. This file shows the UFSHCD manufacturer id. + The Manufacturer ID is defined by JEDEC in JEDEC-JEP106. + The file is read only. diff --git a/MAINTAINERS b/MAINTAINERS index 42decde38320..9a33ab69abab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10173,7 +10173,7 @@ F: Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt F: drivers/infiniband/hw/hns/ HISILICON SAS Controller -M: Xiang Chen +M: Yihang Li S: Supported W: http://www.hisilicon.com F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt @@ -20351,6 +20351,7 @@ F: Documentation/devicetree/bindings/scsi/ F: drivers/scsi/ F: drivers/ufs/ F: include/scsi/ +F: include/uapi/scsi/ SCSI TAPE DRIVER M: Kai Mäkisara diff --git a/block/blk-core.c b/block/blk-core.c index 1217c2cd66dd..bc5e8c5eaac9 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -799,6 +799,7 @@ void submit_bio_noacct(struct bio *bio) switch (bio_op(bio)) { case REQ_OP_READ: + break; case REQ_OP_WRITE: if (bio->bi_opf & REQ_ATOMIC) { status = blk_validate_atomic_write_op_size(q, bio); diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index 3770cb1cff7d..1167a16d8fb4 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1018,14 +1018,6 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL #define MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE (0x08) -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_2_RAID_VOLUME_MAX -#define MPI_IOC_PAGE_2_RAID_VOLUME_MAX (1) -#endif - typedef struct _CONFIG_PAGE_IOC_2 { CONFIG_PAGE_HEADER Header; /* 00h */ @@ -1034,7 +1026,7 @@ typedef struct _CONFIG_PAGE_IOC_2 U8 MaxVolumes; /* 09h */ U8 NumActivePhysDisks; /* 0Ah */ U8 MaxPhysDisks; /* 0Bh */ - CONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */ + CONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[] __counted_by(NumActiveVolumes); /* 0Ch */ } CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, IOCPage2_t, MPI_POINTER pIOCPage2_t; @@ -1064,21 +1056,13 @@ typedef struct _IOC_3_PHYS_DISK } IOC_3_PHYS_DISK, MPI_POINTER PTR_IOC_3_PHYS_DISK, Ioc3PhysDisk_t, MPI_POINTER pIoc3PhysDisk_t; -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_3_PHYSDISK_MAX -#define MPI_IOC_PAGE_3_PHYSDISK_MAX (1) -#endif - typedef struct _CONFIG_PAGE_IOC_3 { CONFIG_PAGE_HEADER Header; /* 00h */ U8 NumPhysDisks; /* 04h */ U8 Reserved1; /* 05h */ U16 Reserved2; /* 06h */ - IOC_3_PHYS_DISK PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */ + IOC_3_PHYS_DISK PhysDisk[] __counted_by(NumPhysDisks); /* 08h */ } CONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3, IOCPage3_t, MPI_POINTER pIOCPage3_t; @@ -1093,21 +1077,13 @@ typedef struct _IOC_4_SEP } IOC_4_SEP, MPI_POINTER PTR_IOC_4_SEP, Ioc4Sep_t, MPI_POINTER pIoc4Sep_t; -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_IOC_PAGE_4_SEP_MAX -#define MPI_IOC_PAGE_4_SEP_MAX (1) -#endif - typedef struct _CONFIG_PAGE_IOC_4 { CONFIG_PAGE_HEADER Header; /* 00h */ U8 ActiveSEP; /* 04h */ U8 MaxSEP; /* 05h */ U16 Reserved1; /* 06h */ - IOC_4_SEP SEP[MPI_IOC_PAGE_4_SEP_MAX]; /* 08h */ + IOC_4_SEP SEP[] __counted_by(ActiveSEP); /* 08h */ } CONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4, IOCPage4_t, MPI_POINTER pIOCPage4_t; @@ -2295,14 +2271,6 @@ typedef struct _RAID_VOL0_SETTINGS #define MPI_RAID_HOT_SPARE_POOL_6 (0x40) #define MPI_RAID_HOT_SPARE_POOL_7 (0x80) -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX -#define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) -#endif - typedef struct _CONFIG_PAGE_RAID_VOL_0 { CONFIG_PAGE_HEADER Header; /* 00h */ @@ -2321,7 +2289,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0 U8 DataScrubRate; /* 25h */ U8 ResyncRate; /* 26h */ U8 InactiveStatus; /* 27h */ - RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */ + RAID_VOL0_PHYS_DISK PhysDisk[] __counted_by(NumPhysDisks); /* 28h */ } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; @@ -2455,14 +2423,6 @@ typedef struct _RAID_PHYS_DISK1_PATH #define MPI_RAID_PHYSDISK1_FLAG_INVALID (0x0001) -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength or NumPhysDiskPaths at runtime. - */ -#ifndef MPI_RAID_PHYS_DISK1_PATH_MAX -#define MPI_RAID_PHYS_DISK1_PATH_MAX (1) -#endif - typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1 { CONFIG_PAGE_HEADER Header; /* 00h */ @@ -2470,7 +2430,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1 U8 PhysDiskNum; /* 05h */ U16 Reserved2; /* 06h */ U32 Reserved1; /* 08h */ - RAID_PHYS_DISK1_PATH Path[MPI_RAID_PHYS_DISK1_PATH_MAX];/* 0Ch */ + RAID_PHYS_DISK1_PATH Path[] __counted_by(NumPhysDiskPaths);/* 0Ch */ } CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1, RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t; @@ -2555,14 +2515,6 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA } MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA, SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData; -/* - * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. - */ -#ifndef MPI_SAS_IOUNIT0_PHY_MAX -#define MPI_SAS_IOUNIT0_PHY_MAX (1) -#endif - typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 { CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ @@ -2571,7 +2523,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 U8 NumPhys; /* 0Ch */ U8 Reserved2; /* 0Dh */ U16 Reserved3; /* 0Eh */ - MPI_SAS_IO_UNIT0_PHY_DATA PhyData[MPI_SAS_IOUNIT0_PHY_MAX]; /* 10h */ + MPI_SAS_IO_UNIT0_PHY_DATA PhyData[] __counted_by(NumPhys); /* 10h */ } CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0, SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t; diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index cea3a79d538e..0e10502660de 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -157,7 +157,6 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } ncmd->status = 0; - ncmd->message = 0; } static inline void advance_sg_buffer(struct NCR5380_cmd *ncmd) @@ -199,7 +198,6 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd) * Polls the chip in a reasonably efficient manner waiting for an * event to occur. After a short quick poll we begin to yield the CPU * (if possible). In irq contexts the time-out is arbitrarily limited. - * Callers may hold locks as long as they are held in irq mode. * * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. */ @@ -1228,24 +1226,15 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) return ret; } -/* - * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using polled I/O - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer, - * can_sleep - 1 or 0 when sleeping is permitted or not, respectively. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transferred or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. +/** + * NCR5380_transfer_pio() - transfers data in given phase using polled I/O + * @instance: instance of driver + * @phase: pointer to what phase is expected + * @count: pointer to number of bytes to transfer + * @data: pointer to data pointer + * @can_sleep: 1 or 0 when sleeping is permitted or not, respectively * - * XXX Note : handling for bus free may be useful. + * Returns: void. *phase, *count, *data are modified in place. */ /* @@ -1254,9 +1243,9 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * counts, we will always do a pseudo DMA or DMA transfer. */ -static int NCR5380_transfer_pio(struct Scsi_Host *instance, - unsigned char *phase, int *count, - unsigned char **data, unsigned int can_sleep) +static void NCR5380_transfer_pio(struct Scsi_Host *instance, + unsigned char *phase, int *count, + unsigned char **data, unsigned int can_sleep) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char p = *phase, tmp; @@ -1277,8 +1266,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, * valid */ - if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, - HZ * can_sleep) < 0) + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ | SR_BSY, + SR_REQ | SR_BSY, HZ * can_sleep) < 0) break; dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); @@ -1329,17 +1318,19 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); -/* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. - * - * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. - * - * 3. ACK and ATN are clear and the target may proceed as normal. - */ + /* + * We have several special cases to consider during REQ/ACK + * handshaking: + * + * 1. We were in MSGOUT phase, and we are on the last byte of + * the message. ATN must be dropped as ACK is dropped. + * + * 2. We are in MSGIN phase, and we are on the last byte of the + * message. We must exit with ACK asserted, so that the calling + * code may raise ATN before dropping ACK to reject the message. + * + * 3. ACK and ATN are clear & the target may proceed as normal. + */ if (!(p == PHASE_MSGIN && c == 1)) { if (p == PHASE_MSGOUT && c > 1) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1361,11 +1352,6 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, *phase = tmp & PHASE_MASK; else *phase = PHASE_UNKNOWN; - - if (!c || (*phase == p)) - return 0; - else - return -1; } /** @@ -1485,6 +1471,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char **data) { struct NCR5380_hostdata *hostdata = shost_priv(instance); + struct NCR5380_cmd *ncmd = NCR5380_to_ncmd(hostdata->connected); int c = *count; unsigned char p = *phase; unsigned char *d = *data; @@ -1496,7 +1483,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, return -1; } - NCR5380_to_ncmd(hostdata->connected)->phase = p; + ncmd->phase = p; if (p & SR_IO) { if (hostdata->read_overruns) @@ -1574,79 +1561,80 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, /* The result is zero iff pseudo DMA send/receive was completed. */ hostdata->dma_len = c; -/* - * A note regarding the DMA errata workarounds for early NMOS silicon. - * - * For DMA sends, we want to wait until the last byte has been - * transferred out over the bus before we turn off DMA mode. Alas, there - * seems to be no terribly good way of doing this on a 5380 under all - * conditions. For non-scatter-gather operations, we can wait until REQ - * and ACK both go false, or until a phase mismatch occurs. Gather-sends - * are nastier, since the device will be expecting more data than we - * are prepared to send it, and REQ will remain asserted. On a 53C8[01] we - * could test Last Byte Sent to assure transfer (I imagine this is precisely - * why this signal was added to the newer chips) but on the older 538[01] - * this signal does not exist. The workaround for this lack is a watchdog; - * we bail out of the wait-loop after a modest amount of wait-time if - * the usual exit conditions are not met. Not a terribly clean or - * correct solution :-% - * - * DMA receive is equally tricky due to a nasty characteristic of the NCR5380. - * If the chip is in DMA receive mode, it will respond to a target's - * REQ by latching the SCSI data into the INPUT DATA register and asserting - * ACK, even if it has _already_ been notified by the DMA controller that - * the current DMA transfer has completed! If the NCR5380 is then taken - * out of DMA mode, this already-acknowledged byte is lost. This is - * not a problem for "one DMA transfer per READ command", because - * the situation will never arise... either all of the data is DMA'ed - * properly, or the target switches to MESSAGE IN phase to signal a - * disconnection (either operation bringing the DMA to a clean halt). - * However, in order to handle scatter-receive, we must work around the - * problem. The chosen fix is to DMA fewer bytes, then check for the - * condition before taking the NCR5380 out of DMA mode. One or two extra - * bytes are transferred via PIO as necessary to fill out the original - * request. - */ - - if (hostdata->flags & FLAG_DMA_FIXUP) { - if (p & SR_IO) { - /* - * The workaround was to transfer fewer bytes than we - * intended to with the pseudo-DMA read function, wait for - * the chip to latch the last byte, read it, and then disable - * pseudo-DMA mode. - * - * After REQ is asserted, the NCR5380 asserts DRQ and ACK. - * REQ is deasserted when ACK is asserted, and not reasserted - * until ACK goes false. Since the NCR5380 won't lower ACK - * until DACK is asserted, which won't happen unless we twiddle - * the DMA port or we take the NCR5380 out of DMA mode, we - * can guarantee that we won't handshake another extra - * byte. - */ + /* + * A note regarding the DMA errata workarounds for early NMOS silicon. + * + * For DMA sends, we want to wait until the last byte has been + * transferred out over the bus before we turn off DMA mode. Alas, there + * seems to be no terribly good way of doing this on a 5380 under all + * conditions. For non-scatter-gather operations, we can wait until REQ + * and ACK both go false, or until a phase mismatch occurs. Gather-sends + * are nastier, since the device will be expecting more data than we + * are prepared to send it, and REQ will remain asserted. On a 53C8[01] + * we could test Last Byte Sent to assure transfer (I imagine this is + * precisely why this signal was added to the newer chips) but on the + * older 538[01] this signal does not exist. The workaround for this + * lack is a watchdog; we bail out of the wait-loop after a modest + * amount of wait-time if the usual exit conditions are not met. + * Not a terribly clean or correct solution :-% + * + * DMA receive is equally tricky due to a nasty characteristic of the + * NCR5380. If the chip is in DMA receive mode, it will respond to a + * target's REQ by latching the SCSI data into the INPUT DATA register + * and asserting ACK, even if it has _already_ been notified by the + * DMA controller that the current DMA transfer has completed! If the + * NCR5380 is then taken out of DMA mode, this already-acknowledged + * byte is lost. + * + * This is not a problem for "one DMA transfer per READ + * command", because the situation will never arise... either all of + * the data is DMA'ed properly, or the target switches to MESSAGE IN + * phase to signal a disconnection (either operation bringing the DMA + * to a clean halt). However, in order to handle scatter-receive, we + * must work around the problem. The chosen fix is to DMA fewer bytes, + * then check for the condition before taking the NCR5380 out of DMA + * mode. One or two extra bytes are transferred via PIO as necessary + * to fill out the original request. + */ - if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, - BASR_DRQ, BASR_DRQ, 0) < 0) { - result = -1; - shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); - } - if (NCR5380_poll_politely(hostdata, STATUS_REG, - SR_REQ, 0, 0) < 0) { - result = -1; - shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); - } - d[*count - 1] = NCR5380_read(INPUT_DATA_REG); - } else { - /* - * Wait for the last byte to be sent. If REQ is being asserted for - * the byte we're interested, we'll ACK it and it will go false. - */ - if (NCR5380_poll_politely2(hostdata, - BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, - BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0) < 0) { - result = -1; - shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); + if ((hostdata->flags & FLAG_DMA_FIXUP) && + (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { + /* + * The workaround was to transfer fewer bytes than we + * intended to with the pseudo-DMA receive function, wait for + * the chip to latch the last byte, read it, and then disable + * DMA mode. + * + * After REQ is asserted, the NCR5380 asserts DRQ and ACK. + * REQ is deasserted when ACK is asserted, and not reasserted + * until ACK goes false. Since the NCR5380 won't lower ACK + * until DACK is asserted, which won't happen unless we twiddle + * the DMA port or we take the NCR5380 out of DMA mode, we + * can guarantee that we won't handshake another extra + * byte. + * + * If sending, wait for the last byte to be sent. If REQ is + * being asserted for the byte we're interested, we'll ACK it + * and it will go false. + */ + if (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, + BASR_DRQ, BASR_DRQ, 0)) { + if ((p & SR_IO) && + (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { + if (!NCR5380_poll_politely(hostdata, STATUS_REG, + SR_REQ, 0, 0)) { + d[c] = NCR5380_read(INPUT_DATA_REG); + --ncmd->this_residual; + } else { + result = -1; + scmd_printk(KERN_ERR, hostdata->connected, + "PDMA fixup: !REQ timeout\n"); + } } + } else if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH) { + result = -1; + scmd_printk(KERN_ERR, hostdata->connected, + "PDMA fixup: DRQ timeout\n"); } } @@ -1666,9 +1654,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * Side effects : SCSI things happen, the disconnected queue will be * modified if a command disconnects, *instance->connected will * change. - * - * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. */ static void NCR5380_information_transfer(struct Scsi_Host *instance) @@ -1807,9 +1792,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) return; case PHASE_MSGIN: len = 1; + tmp = 0xff; data = &tmp; NCR5380_transfer_pio(instance, &phase, &len, &data, 0); - ncmd->message = tmp; + if (tmp == 0xff) + break; switch (tmp) { case ABORT: @@ -1996,6 +1983,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) break; case PHASE_STATIN: len = 1; + tmp = ncmd->status; data = &tmp; NCR5380_transfer_pio(instance, &phase, &len, &data, 0); ncmd->status = tmp; @@ -2005,9 +1993,20 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ } else { + int err; + spin_unlock_irq(&hostdata->lock); - NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ); + err = NCR5380_poll_politely(hostdata, STATUS_REG, + SR_REQ, SR_REQ, HZ); spin_lock_irq(&hostdata->lock); + + if (err < 0 && hostdata->connected && + !(NCR5380_read(STATUS_REG) & SR_BSY)) { + scmd_printk(KERN_ERR, hostdata->connected, + "BSY signal lost\n"); + do_reset(instance); + bus_reset_cleanup(instance); + } } } } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 8dc2be4212dc..d402d4bffcb2 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -3,10 +3,10 @@ * NCR 5380 defines * * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 + * Visionary Computing + * (Unix consulting and custom programming) + * drew@colorado.edu + * +1 (303) 666-5836 * * For more information, please consult * @@ -78,7 +78,7 @@ #define ICR_DIFF_ENABLE 0x20 /* wo Set to enable diff. drivers */ #define ICR_ASSERT_ACK 0x10 /* rw ini Set to assert ACK */ #define ICR_ASSERT_BSY 0x08 /* rw Set to assert BSY */ -#define ICR_ASSERT_SEL 0x04 /* rw Set to assert SEL */ +#define ICR_ASSERT_SEL 0x04 /* rw Set to assert SEL */ #define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */ #define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */ @@ -135,7 +135,7 @@ #define BASR_IRQ 0x10 /* ro mirror of IRQ pin */ #define BASR_PHASE_MATCH 0x08 /* ro Set when MSG CD IO match TCR */ #define BASR_BUSY_ERROR 0x04 /* ro Unexpected change to inactive state */ -#define BASR_ATN 0x02 /* ro BUS status */ +#define BASR_ATN 0x02 /* ro BUS status */ #define BASR_ACK 0x01 /* ro BUS status */ /* Write any value to this register to start a DMA send */ @@ -170,7 +170,7 @@ #define CSR_BASE CSR_53C80_INTR /* Note : PHASE_* macros are based on the values of the STATUS register */ -#define PHASE_MASK (SR_MSG | SR_CD | SR_IO) +#define PHASE_MASK (SR_MSG | SR_CD | SR_IO) #define PHASE_DATAOUT 0 #define PHASE_DATAIN SR_IO @@ -231,7 +231,6 @@ struct NCR5380_cmd { int this_residual; struct scatterlist *buffer; int status; - int message; int phase; struct list_head list; }; @@ -286,8 +285,9 @@ static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); static bool NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data, - unsigned int can_sleep); +static void NCR5380_transfer_pio(struct Scsi_Host *instance, + unsigned char *phase, int *count, + unsigned char **data, unsigned int can_sleep); static int NCR5380_poll_politely2(struct NCR5380_hostdata *, unsigned int, u8, u8, unsigned int, u8, u8, unsigned long); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b22857c6f3f4..ec3834bda111 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1267,7 +1267,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 return ret; command = ContainerRawIo; fibsize = sizeof(struct aac_raw_io) + - ((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw)); + (le32_to_cpu(readcmd->sg.count) * sizeof(struct sgentryraw)); } BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1302,7 +1302,7 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u if (ret < 0) return ret; fibsize = sizeof(struct aac_read64) + - ((le32_to_cpu(readcmd->sg.count) - 1) * + (le32_to_cpu(readcmd->sg.count) * sizeof (struct sgentry64)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1337,7 +1337,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 if (ret < 0) return ret; fibsize = sizeof(struct aac_read) + - ((le32_to_cpu(readcmd->sg.count) - 1) * + (le32_to_cpu(readcmd->sg.count) * sizeof (struct sgentry)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1401,7 +1401,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u return ret; command = ContainerRawIo; fibsize = sizeof(struct aac_raw_io) + - ((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw)); + (le32_to_cpu(writecmd->sg.count) * sizeof(struct sgentryraw)); } BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1436,7 +1436,7 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, if (ret < 0) return ret; fibsize = sizeof(struct aac_write64) + - ((le32_to_cpu(writecmd->sg.count) - 1) * + (le32_to_cpu(writecmd->sg.count) * sizeof (struct sgentry64)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1473,7 +1473,7 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 if (ret < 0) return ret; fibsize = sizeof(struct aac_write) + - ((le32_to_cpu(writecmd->sg.count) - 1) * + (le32_to_cpu(writecmd->sg.count) * sizeof (struct sgentry)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1592,9 +1592,9 @@ static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) /* * Build Scatter/Gather list */ - fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + + fibsize = sizeof(struct aac_srb) + ((le32_to_cpu(srbcmd->sg.count) & 0xff) * - sizeof (struct sgentry64)); + sizeof(struct sgentry64)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1624,7 +1624,7 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd) * Build Scatter/Gather list */ fibsize = sizeof (struct aac_srb) + - (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * + ((le32_to_cpu(srbcmd->sg.count) & 0xff) * sizeof (struct sgentry)); BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); @@ -1693,8 +1693,7 @@ static int aac_send_safw_bmic_cmd(struct aac_dev *dev, fibptr->hw_fib_va->header.XferState &= ~cpu_to_le32(FastResponseCapable); - fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) + - sizeof(struct sgentry64); + fibsize = sizeof(struct aac_srb) + sizeof(struct sgentry64); /* allocate DMA buffer for response */ addr = dma_map_single(&dev->pdev->dev, xfer_buf, xfer_len, @@ -1833,7 +1832,7 @@ static int aac_get_safw_ciss_luns(struct aac_dev *dev) struct aac_ciss_phys_luns_resp *phys_luns; datasize = sizeof(struct aac_ciss_phys_luns_resp) + - (AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun); + AAC_MAX_TARGETS * sizeof(struct _ciss_lun); phys_luns = kmalloc(datasize, GFP_KERNEL); if (phys_luns == NULL) goto out; @@ -2267,7 +2266,7 @@ int aac_get_adapter_info(struct aac_dev* dev) dev->a_ops.adapter_bounds = aac_bounds_32; dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write) + sizeof(struct sgentry)) / + sizeof(struct aac_write)) / sizeof(struct sgentry); if (dev->dac_support) { dev->a_ops.adapter_read = aac_read_block64; @@ -2278,8 +2277,7 @@ int aac_get_adapter_info(struct aac_dev* dev) dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write64) + - sizeof(struct sgentry64)) / + sizeof(struct aac_write64)) / sizeof(struct sgentry64); } else { dev->a_ops.adapter_read = aac_read_block; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 7d5a155073c6..1d09d3ac6aa4 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -322,7 +322,7 @@ struct aac_ciss_phys_luns_resp { u8 level3[2]; u8 level2[2]; u8 node_ident[16]; /* phys. node identifier */ - } lun[1]; /* List of phys. devices */ + } lun[]; /* List of phys. devices */ }; /* @@ -507,32 +507,27 @@ struct sge_ieee1212 { struct sgmap { __le32 count; - struct sgentry sg[1]; + struct sgentry sg[]; }; struct user_sgmap { u32 count; - struct user_sgentry sg[1]; + struct user_sgentry sg[]; }; struct sgmap64 { __le32 count; - struct sgentry64 sg[1]; + struct sgentry64 sg[]; }; struct user_sgmap64 { u32 count; - struct user_sgentry64 sg[1]; + struct user_sgentry64 sg[]; }; struct sgmapraw { __le32 count; - struct sgentryraw sg[1]; -}; - -struct user_sgmapraw { - u32 count; - struct user_sgentryraw sg[1]; + struct sgentryraw sg[]; }; struct creation_info @@ -873,7 +868,7 @@ union aac_init __le16 element_count; __le16 comp_thresh; __le16 unused; - } rrq[1]; /* up to 64 RRQ addresses */ + } rrq[] __counted_by_le(rr_queue_count); /* up to 64 RRQ addresses */ } r8; }; @@ -2029,8 +2024,8 @@ struct aac_srb_reply }; struct aac_srb_unit { - struct aac_srb srb; struct aac_srb_reply srb_reply; + struct aac_srb srb; }; /* diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index e7cc927ed952..68240d6f27ab 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -523,7 +523,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) goto cleanup; } - if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || + if ((fibsize < sizeof(struct user_aac_srb)) || (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { rcode = -EINVAL; goto cleanup; @@ -561,7 +561,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -EINVAL; goto cleanup; } - actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) + + actual_fibsize = sizeof(struct aac_srb) + ((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry)); actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) * (sizeof(struct sgentry64) - sizeof(struct sgentry)); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index bd99c5492b7d..fee857236991 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -522,8 +522,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) spin_lock_init(&dev->iq_lock); dev->max_fib_size = sizeof(struct hw_fib); dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size - - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write) + sizeof(struct sgentry)) + - sizeof(struct aac_fibhdr) - sizeof(struct aac_write)) / sizeof(struct sgentry); dev->comm_interface = AAC_COMM_PRODUCER; dev->raw_io_interface = dev->raw_io_64 = 0; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 25cee03d7f97..47287559c768 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -2327,8 +2327,9 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str, sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); sg64->sg[0].count = cpu_to_le32(datasize); - ret = aac_fib_send(ScsiPortCommand64, fibptr, sizeof(struct aac_srb), - FsaNormal, 1, 1, NULL, NULL); + ret = aac_fib_send(ScsiPortCommand64, fibptr, + sizeof(struct aac_srb) + sizeof(struct sgentry), + FsaNormal, 1, 1, NULL, NULL); dma_free_coherent(&dev->pdev->dev, datasize, dma_buf, addr); diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 11ef58204e96..28115ed637e8 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -410,7 +410,7 @@ static void aac_src_start_adapter(struct aac_dev *dev) lower_32_bits(dev->init_pa), upper_32_bits(dev->init_pa), sizeof(struct _r8) + - (AAC_MAX_HRRQ - 1) * sizeof(struct _rrq), + AAC_MAX_HRRQ * sizeof(struct _rrq), 0, 0, 0, NULL, NULL, NULL, NULL, NULL); } else { init->r7.host_elapsed_seconds = diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index c77d6ca1a210..b2b643c6dbbe 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1030,7 +1030,7 @@ struct ipr_hostrcb_fabric_desc { #define IPR_PATH_FAILED 0x03 __be16 num_entries; - struct ipr_hostrcb_config_element elem[1]; + struct ipr_hostrcb_config_element elem[]; }__attribute__((packed, aligned (4))); struct ipr_hostrcb64_fabric_desc { @@ -1044,7 +1044,7 @@ struct ipr_hostrcb64_fabric_desc { u8 res_path[8]; u8 reserved3[6]; __be16 num_entries; - struct ipr_hostrcb64_config_element elem[1]; + struct ipr_hostrcb64_config_element elem[]; }__attribute__((packed, aligned (8))); #define for_each_hrrq(hrrq, ioa_cfg) \ diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 7c147d6ea8a8..e5a9c5a323f8 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -306,6 +306,14 @@ struct lpfc_stats { struct lpfc_hba; +/* Data structure to keep withheld FLOGI_ACC information */ +struct lpfc_defer_flogi_acc { + bool flag; + u16 rx_id; + u16 ox_id; + struct lpfc_nodelist *ndlp; + +}; #define LPFC_VMID_TIMER 300 /* timer interval in seconds */ @@ -1430,9 +1438,7 @@ struct lpfc_hba { uint16_t vlan_id; struct list_head fcf_conn_rec_list; - bool defer_flogi_acc_flag; - uint16_t defer_flogi_acc_rx_id; - uint16_t defer_flogi_acc_ox_id; + struct lpfc_defer_flogi_acc defer_flogi_acc; spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */ struct list_head ct_ev_waiters; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 929cbfc95163..de0ec945d2f1 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1099,8 +1099,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, sp->cmn.priority_tagging, kref_read(&ndlp->kref)); /* reinitialize the VMID datastructure before returning */ - if (lpfc_is_vmid_enabled(phba)) + if (lpfc_is_vmid_enabled(phba)) { lpfc_reinit_vmid(vport); + vport->vmid_flag = 0; + } if (sp->cmn.priority_tagging) vport->phba->pport->vmid_flag |= (LPFC_VMID_ISSUE_QFPA | LPFC_VMID_TYPE_PRIO); @@ -1390,7 +1392,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->link_flag &= ~LS_EXTERNAL_LOOPBACK; /* Check for a deferred FLOGI ACC condition */ - if (phba->defer_flogi_acc_flag) { + if (phba->defer_flogi_acc.flag) { /* lookup ndlp for received FLOGI */ ndlp = lpfc_findnode_did(vport, 0); if (!ndlp) @@ -1404,34 +1406,38 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (phba->sli_rev == LPFC_SLI_REV4) { bf_set(wqe_ctxt_tag, &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com, - phba->defer_flogi_acc_rx_id); + phba->defer_flogi_acc.rx_id); bf_set(wqe_rcvoxid, &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com, - phba->defer_flogi_acc_ox_id); + phba->defer_flogi_acc.ox_id); } else { icmd = &defer_flogi_acc.iocb; - icmd->ulpContext = phba->defer_flogi_acc_rx_id; + icmd->ulpContext = phba->defer_flogi_acc.rx_id; icmd->unsli3.rcvsli3.ox_id = - phba->defer_flogi_acc_ox_id; + phba->defer_flogi_acc.ox_id; } lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3354 Xmit deferred FLOGI ACC: rx_id: x%x," " ox_id: x%x, hba_flag x%lx\n", - phba->defer_flogi_acc_rx_id, - phba->defer_flogi_acc_ox_id, phba->hba_flag); + phba->defer_flogi_acc.rx_id, + phba->defer_flogi_acc.ox_id, phba->hba_flag); /* Send deferred FLOGI ACC */ lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc, ndlp, NULL); - phba->defer_flogi_acc_flag = false; - vport->fc_myDID = did; + phba->defer_flogi_acc.flag = false; - /* Decrement ndlp reference count to indicate the node can be - * released when other references are removed. + /* Decrement the held ndlp that was incremented when the + * deferred flogi acc flag was set. */ - lpfc_nlp_put(ndlp); + if (phba->defer_flogi_acc.ndlp) { + lpfc_nlp_put(phba->defer_flogi_acc.ndlp); + phba->defer_flogi_acc.ndlp = NULL; + } + + vport->fc_myDID = did; } return 0; @@ -5240,9 +5246,10 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* ACC to LOGO completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0109 ACC to LOGO completes to NPort x%x refcnt %d " - "Data: x%x x%x x%x\n", - ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag, - ndlp->nlp_state, ndlp->nlp_rpi); + "last els x%x Data: x%x x%x x%x\n", + ndlp->nlp_DID, kref_read(&ndlp->kref), + ndlp->nlp_last_elscmd, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); /* This clause allows the LOGO ACC to complete and free resources * for the Fabric Domain Controller. It does deliberately skip @@ -5254,18 +5261,22 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; if (ndlp->nlp_state == NLP_STE_NPR_NODE) { - /* If PLOGI is being retried, PLOGI completion will cleanup the - * node. The NLP_NPR_2B_DISC flag needs to be retained to make - * progress on nodes discovered from last RSCN. - */ - if ((ndlp->nlp_flag & NLP_DELAY_TMO) && - (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI)) - goto out; - if (ndlp->nlp_flag & NLP_RPI_REGISTERED) lpfc_unreg_rpi(vport, ndlp); + /* If came from PRLO, then PRLO_ACC is done. + * Start rediscovery now. + */ + if (ndlp->nlp_last_elscmd == ELS_CMD_PRLO) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); + ndlp->nlp_prev_state = ndlp->nlp_state; + lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); + lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); + } } + out: /* * The driver received a LOGO from the rport and has ACK'd it. @@ -8454,9 +8465,9 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, /* Defer ACC response until AFTER we issue a FLOGI */ if (!test_bit(HBA_FLOGI_ISSUED, &phba->hba_flag)) { - phba->defer_flogi_acc_rx_id = bf_get(wqe_ctxt_tag, + phba->defer_flogi_acc.rx_id = bf_get(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com); - phba->defer_flogi_acc_ox_id = bf_get(wqe_rcvoxid, + phba->defer_flogi_acc.ox_id = bf_get(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com); vport->fc_myDID = did; @@ -8464,11 +8475,17 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3344 Deferring FLOGI ACC: rx_id: x%x," " ox_id: x%x, hba_flag x%lx\n", - phba->defer_flogi_acc_rx_id, - phba->defer_flogi_acc_ox_id, phba->hba_flag); + phba->defer_flogi_acc.rx_id, + phba->defer_flogi_acc.ox_id, phba->hba_flag); - phba->defer_flogi_acc_flag = true; + phba->defer_flogi_acc.flag = true; + /* This nlp_get is paired with nlp_puts that reset the + * defer_flogi_acc.flag back to false. We need to retain + * a kref on the ndlp until the deferred FLOGI ACC is + * processed or cancelled. + */ + phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp); return 0; } @@ -10504,7 +10521,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_rcv_flogi(vport, elsiocb, ndlp); /* retain node if our response is deferred */ - if (phba->defer_flogi_acc_flag) + if (phba->defer_flogi_acc.flag) break; if (newnode) lpfc_disc_state_machine(vport, ndlp, NULL, @@ -10742,7 +10759,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_NOTHING_MORE; /* Unknown ELS command received from NPORT */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, "0115 Unknown ELS command x%x " "received from NPORT x%x\n", cmd, did); if (newnode) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 6943f6c6395c..35c9181c6608 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -175,7 +175,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ndlp->nlp_state, ndlp->fc4_xpt_flags); /* Don't schedule a worker thread event if the vport is going down. */ - if (test_bit(FC_UNLOADING, &vport->load_flag)) { + if (test_bit(FC_UNLOADING, &vport->load_flag) || + !test_bit(HBA_SETUP, &phba->hba_flag)) { spin_lock_irqsave(&ndlp->lock, iflags); ndlp->rport = NULL; @@ -1254,7 +1255,14 @@ lpfc_linkdown(struct lpfc_hba *phba) lpfc_scsi_dev_block(phba); offline = pci_channel_offline(phba->pcidev); - phba->defer_flogi_acc_flag = false; + /* Decrement the held ndlp if there is a deferred flogi acc */ + if (phba->defer_flogi_acc.flag) { + if (phba->defer_flogi_acc.ndlp) { + lpfc_nlp_put(phba->defer_flogi_acc.ndlp); + phba->defer_flogi_acc.ndlp = NULL; + } + } + phba->defer_flogi_acc.flag = false; /* Clear external loopback plug detected flag */ phba->link_flag &= ~LS_EXTERNAL_LOOPBACK; @@ -1376,7 +1384,7 @@ lpfc_linkup_port(struct lpfc_vport *vport) (vport != phba->pport)) return; - if (phba->defer_flogi_acc_flag) { + if (phba->defer_flogi_acc.flag) { clear_bit(FC_ABORT_DISCOVERY, &vport->fc_flag); clear_bit(FC_RSCN_MODE, &vport->fc_flag); clear_bit(FC_NLP_MORE, &vport->fc_flag); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index f6a53446e57f..4574716c8764 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -2652,8 +2652,26 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* flush the target */ lpfc_sli_abort_iocb(vport, ndlp->nlp_sid, 0, LPFC_CTX_TGT); - /* Treat like rcv logo */ - lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); + /* Send PRLO_ACC */ + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_LOGO_ACC; + spin_unlock_irq(&ndlp->lock); + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); + + /* Save ELS_CMD_PRLO as the last elscmd and then set to NPR. + * lpfc_cmpl_els_logo_acc is expected to restart discovery. + */ + ndlp->nlp_last_elscmd = ELS_CMD_PRLO; + ndlp->nlp_prev_state = ndlp->nlp_state; + + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_ELS | LOG_DISCOVERY, + "3422 DID x%06x nflag x%x lastels x%x ref cnt %u\n", + ndlp->nlp_DID, ndlp->nlp_flag, + ndlp->nlp_last_elscmd, + kref_read(&ndlp->kref)); + + lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); + return ndlp->nlp_state; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 98ce9d97a225..60cd60ebff38 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5555,11 +5555,20 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) iocb = &lpfc_cmd->cur_iocbq; if (phba->sli_rev == LPFC_SLI_REV4) { - pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring; - if (!pring_s4) { + /* if the io_wq & pring are gone, the port was reset. */ + if (!phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq || + !phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "2877 SCSI Layer I/O Abort Request " + "IO CMPL Status x%x ID %d LUN %llu " + "HBA_SETUP %d\n", FAILED, + cmnd->device->id, + (u64)cmnd->device->lun, + test_bit(HBA_SETUP, &phba->hba_flag)); ret = FAILED; goto out_unlock_hba; } + pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring; spin_lock(&pring_s4->ring_lock); } /* the command is in process of being cancelled */ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 88debef2fb6d..332b8d2348e9 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4687,6 +4687,17 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) /* Look on all the FCP Rings for the iotag */ if (phba->sli_rev >= LPFC_SLI_REV4) { for (i = 0; i < phba->cfg_hdw_queue; i++) { + if (!phba->sli4_hba.hdwq || + !phba->sli4_hba.hdwq[i].io_wq) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "7777 hdwq's deleted %lx " + "%lx %x %x\n", + phba->pport->load_flag, + phba->hba_flag, + phba->link_state, + phba->sli.sli_flag); + return; + } pring = phba->sli4_hba.hdwq[i].io_wq->pring; spin_lock_irq(&pring->ring_lock); @@ -12473,8 +12484,6 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, cmdiocb->iocb.ulpClass, LPFC_WQE_CQ_ID_DEFAULT, ia, false); - abtsiocbp->vport = vport; - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; if (cmdiocb->cmd_flag & LPFC_IO_FCP) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 7ac9ef281881..2fe0386a1fee 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.4.0.3" +#define LPFC_DRIVER_VERSION "14.4.0.4" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/lpfc/lpfc_vmid.c b/drivers/scsi/lpfc/lpfc_vmid.c index 773e02ae20c3..cc3e4736f2fe 100644 --- a/drivers/scsi/lpfc/lpfc_vmid.c +++ b/drivers/scsi/lpfc/lpfc_vmid.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -321,6 +321,5 @@ lpfc_reinit_vmid(struct lpfc_vport *vport) if (!hash_empty(vport->hash_table)) hash_for_each_safe(vport->hash_table, bucket, tmp, cur, hnode) hash_del(&cur->hnode); - vport->vmid_flag = 0; write_unlock(&vport->vmid_lock); } diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 53ee8f84d094..f225bb20aa22 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -102,11 +102,15 @@ __setup("mac5380=", mac_scsi_setup); * Linux SCSI drivers lack knowledge of the timing behaviour of SCSI targets * so bus errors are unavoidable. * - * If a MOVE.B instruction faults, we assume that zero bytes were transferred - * and simply retry. That assumption probably depends on target behaviour but - * seems to hold up okay. The NOP provides synchronization: without it the - * fault can sometimes occur after the program counter has moved past the - * offending instruction. Post-increment addressing can't be used. + * If a MOVE.B instruction faults during a receive operation, we assume the + * target sent nothing and try again. That assumption probably depends on + * target firmware but it seems to hold up okay. If a fault happens during a + * send operation, the target may or may not have seen /ACK and got the byte. + * It's uncertain so the whole SCSI command gets retried. + * + * The NOP is needed for synchronization because the fault address in the + * exception stack frame may or may not be the instruction that actually + * caused the bus error. Post-increment addressing can't be used. */ #define MOVE_BYTE(operands) \ @@ -208,8 +212,6 @@ __setup("mac5380=", mac_scsi_setup); ".previous \n" \ : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) -#define MAC_PDMA_DELAY 32 - static inline int mac_pdma_recv(void __iomem *io, unsigned char *start, int n) { unsigned char *addr = start; @@ -245,22 +247,21 @@ static inline int mac_pdma_send(unsigned char *start, void __iomem *io, int n) if (n >= 1) { MOVE_BYTE("%0@,%3@"); if (result) - goto out; + return -1; } if (n >= 1 && ((unsigned long)addr & 1)) { MOVE_BYTE("%0@,%3@"); if (result) - goto out; + return -2; } while (n >= 32) MOVE_16_WORDS("%0@+,%3@"); while (n >= 2) MOVE_WORD("%0@+,%3@"); if (result) - return start - addr; /* Negated to indicate uncertain length */ + return start - addr - 1; /* Negated to indicate uncertain length */ if (n == 1) MOVE_BYTE("%0@,%3@"); -out: return addr - start; } @@ -274,25 +275,56 @@ static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value) out_be32(hostdata->io + (CTRL_REG << 4), value); } +static inline int macscsi_wait_for_drq(struct NCR5380_hostdata *hostdata) +{ + unsigned int n = 1; /* effectively multiplies NCR5380_REG_POLL_TIME */ + unsigned char basr; + +again: + basr = NCR5380_read(BUS_AND_STATUS_REG); + + if (!(basr & BASR_PHASE_MATCH)) + return 1; + + if (basr & BASR_IRQ) + return -1; + + if (basr & BASR_DRQ) + return 0; + + if (n-- == 0) { + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); + dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, + "%s: DRQ timeout\n", __func__); + return -1; + } + + NCR5380_poll_politely2(hostdata, + BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, + BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0); + goto again; +} + static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, unsigned char *dst, int len) { u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); unsigned char *d = dst; - int result = 0; hostdata->pdma_residual = len; - while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, - BASR_DRQ | BASR_PHASE_MATCH, - BASR_DRQ | BASR_PHASE_MATCH, 0)) { - int bytes; + while (macscsi_wait_for_drq(hostdata) == 0) { + int bytes, chunk_bytes; if (macintosh_config->ident == MAC_MODEL_IIFX) write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | CTRL_INTERRUPTS_ENABLE); - bytes = mac_pdma_recv(s, d, min(hostdata->pdma_residual, 512)); + chunk_bytes = min(hostdata->pdma_residual, 512); + bytes = mac_pdma_recv(s, d, chunk_bytes); + + if (macintosh_config->ident == MAC_MODEL_IIFX) + write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); if (bytes > 0) { d += bytes; @@ -300,37 +332,25 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, } if (hostdata->pdma_residual == 0) - goto out; + break; - if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, - BUS_AND_STATUS_REG, BASR_ACK, - BASR_ACK, 0) < 0) - scmd_printk(KERN_DEBUG, hostdata->connected, - "%s: !REQ and !ACK\n", __func__); - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) - goto out; + if (bytes > 0) + continue; - if (bytes == 0) - udelay(MAC_PDMA_DELAY); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); + dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, + "%s: bus error [%d/%d] (%d/%d)\n", + __func__, d - dst, len, bytes, chunk_bytes); - if (bytes >= 0) + if (bytes == 0) continue; - dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, - "%s: bus error (%d/%d)\n", __func__, d - dst, len); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); - result = -1; - goto out; + if (macscsi_wait_for_drq(hostdata) <= 0) + set_host_byte(hostdata->connected, DID_ERROR); + break; } - scmd_printk(KERN_ERR, hostdata->connected, - "%s: phase mismatch or !DRQ\n", __func__); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); - result = -1; -out: - if (macintosh_config->ident == MAC_MODEL_IIFX) - write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); - return result; + return 0; } static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, @@ -338,67 +358,47 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, { unsigned char *s = src; u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); - int result = 0; hostdata->pdma_residual = len; - while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, - BASR_DRQ | BASR_PHASE_MATCH, - BASR_DRQ | BASR_PHASE_MATCH, 0)) { - int bytes; + while (macscsi_wait_for_drq(hostdata) == 0) { + int bytes, chunk_bytes; if (macintosh_config->ident == MAC_MODEL_IIFX) write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | CTRL_INTERRUPTS_ENABLE); - bytes = mac_pdma_send(s, d, min(hostdata->pdma_residual, 512)); + chunk_bytes = min(hostdata->pdma_residual, 512); + bytes = mac_pdma_send(s, d, chunk_bytes); + + if (macintosh_config->ident == MAC_MODEL_IIFX) + write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); if (bytes > 0) { s += bytes; hostdata->pdma_residual -= bytes; } - if (hostdata->pdma_residual == 0) { - if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, - TCR_LAST_BYTE_SENT, - TCR_LAST_BYTE_SENT, - 0) < 0) { - scmd_printk(KERN_ERR, hostdata->connected, - "%s: Last Byte Sent timeout\n", __func__); - result = -1; - } - goto out; - } + if (hostdata->pdma_residual == 0) + break; - if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, - BUS_AND_STATUS_REG, BASR_ACK, - BASR_ACK, 0) < 0) - scmd_printk(KERN_DEBUG, hostdata->connected, - "%s: !REQ and !ACK\n", __func__); - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) - goto out; + if (bytes > 0) + continue; - if (bytes == 0) - udelay(MAC_PDMA_DELAY); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); + dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, + "%s: bus error [%d/%d] (%d/%d)\n", + __func__, s - src, len, bytes, chunk_bytes); - if (bytes >= 0) + if (bytes == 0) continue; - dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, - "%s: bus error (%d/%d)\n", __func__, s - src, len); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); - result = -1; - goto out; + if (macscsi_wait_for_drq(hostdata) <= 0) + set_host_byte(hostdata->connected, DID_ERROR); + break; } - scmd_printk(KERN_ERR, hostdata->connected, - "%s: phase mismatch or !DRQ\n", __func__); - NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); - result = -1; -out: - if (macintosh_config->ident == MAC_MODEL_IIFX) - write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); - return result; + return 0; } static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, @@ -432,7 +432,7 @@ static struct scsi_host_template mac_scsi_template = { .eh_host_reset_handler = macscsi_host_reset, .can_queue = 16, .this_id = 7, - .sg_tablesize = 1, + .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .dma_boundary = PAGE_SIZE - 1, .cmd_size = sizeof(struct NCR5380_cmd), @@ -470,6 +470,9 @@ static int __init mac_scsi_probe(struct platform_device *pdev) if (setup_hostid >= 0) mac_scsi_template.this_id = setup_hostid & 7; + if (macintosh_config->ident == MAC_MODEL_IIFX) + mac_scsi_template.sg_tablesize = 1; + instance = scsi_host_alloc(&mac_scsi_template, sizeof(struct NCR5380_hostdata)); if (!instance) @@ -491,6 +494,9 @@ static int __init mac_scsi_probe(struct platform_device *pdev) host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; + if (instance->sg_tablesize > 1) + host_flags |= FLAG_DMA_FIXUP; + error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); if (error) goto fail_init; diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 5680c6cdb221..088cc40ae866 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -814,12 +814,12 @@ struct MR_HOST_DEVICE_LIST { __le32 size; __le32 count; __le32 reserved[2]; - struct MR_HOST_DEVICE_LIST_ENTRY host_device_list[1]; + struct MR_HOST_DEVICE_LIST_ENTRY host_device_list[] __counted_by_le(count); } __packed; #define HOST_DEVICE_LIST_SZ (sizeof(struct MR_HOST_DEVICE_LIST) + \ (sizeof(struct MR_HOST_DEVICE_LIST_ENTRY) * \ - (MEGASAS_MAX_PD + MAX_LOGICAL_DRIVES_EXT - 1))) + (MEGASAS_MAX_PD + MAX_LOGICAL_DRIVES_EXT))) /* @@ -2473,7 +2473,7 @@ struct MR_LD_VF_MAP { union MR_LD_REF ref; u8 ldVfCount; u8 reserved[6]; - u8 policy[1]; + u8 policy[]; }; struct MR_LD_VF_AFFILIATION { diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 6a19e17eb1a7..4b7a8f6314a3 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -1565,16 +1565,13 @@ struct mpi3_sas_io_unit0_phy_data { __le32 reserved10; }; -#ifndef MPI3_SAS_IO_UNIT0_PHY_MAX -#define MPI3_SAS_IO_UNIT0_PHY_MAX (1) -#endif struct mpi3_sas_io_unit_page0 { struct mpi3_config_page_header header; __le32 reserved08; u8 num_phys; u8 init_status; __le16 reserved0e; - struct mpi3_sas_io_unit0_phy_data phy_data[MPI3_SAS_IO_UNIT0_PHY_MAX]; + struct mpi3_sas_io_unit0_phy_data phy_data[]; }; #define MPI3_SASIOUNIT0_PAGEVERSION (0x00) @@ -1606,9 +1603,6 @@ struct mpi3_sas_io_unit1_phy_data { __le32 reserved08; }; -#ifndef MPI3_SAS_IO_UNIT1_PHY_MAX -#define MPI3_SAS_IO_UNIT1_PHY_MAX (1) -#endif struct mpi3_sas_io_unit_page1 { struct mpi3_config_page_header header; __le16 control_flags; @@ -1618,7 +1612,7 @@ struct mpi3_sas_io_unit_page1 { u8 num_phys; u8 sata_max_q_depth; __le16 reserved12; - struct mpi3_sas_io_unit1_phy_data phy_data[MPI3_SAS_IO_UNIT1_PHY_MAX]; + struct mpi3_sas_io_unit1_phy_data phy_data[]; }; #define MPI3_SASIOUNIT1_PAGEVERSION (0x00) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index 028784949873..c9fa0d69b75f 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -453,9 +453,6 @@ struct mpi3_event_data_sas_notify_primitive { #define MPI3_EVENT_NOTIFY_PRIMITIVE_POWER_LOSS_EXPECTED (0x02) #define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED1 (0x03) #define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED2 (0x04) -#ifndef MPI3_EVENT_SAS_TOPO_PHY_COUNT -#define MPI3_EVENT_SAS_TOPO_PHY_COUNT (1) -#endif struct mpi3_event_sas_topo_phy_entry { __le16 attached_dev_handle; u8 link_rate; @@ -496,7 +493,7 @@ struct mpi3_event_data_sas_topology_change_list { u8 start_phy_num; u8 exp_status; u8 io_unit_port; - struct mpi3_event_sas_topo_phy_entry phy_entry[MPI3_EVENT_SAS_TOPO_PHY_COUNT]; + struct mpi3_event_sas_topo_phy_entry phy_entry[] __counted_by(num_entries); }; #define MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) @@ -545,9 +542,6 @@ struct mpi3_event_data_pcie_enumeration { #define MPI3_EVENT_PCIE_ENUM_ES_MAX_SWITCHES_EXCEED (0x40000000) #define MPI3_EVENT_PCIE_ENUM_ES_MAX_DEVICES_EXCEED (0x20000000) #define MPI3_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED (0x10000000) -#ifndef MPI3_EVENT_PCIE_TOPO_PORT_COUNT -#define MPI3_EVENT_PCIE_TOPO_PORT_COUNT (1) -#endif struct mpi3_event_pcie_topo_port_entry { __le16 attached_dev_handle; u8 port_status; @@ -588,7 +582,7 @@ struct mpi3_event_data_pcie_topology_change_list { u8 switch_status; u8 io_unit_port; __le32 reserved0c; - struct mpi3_event_pcie_topo_port_entry port_entry[MPI3_EVENT_PCIE_TOPO_PORT_COUNT]; + struct mpi3_event_pcie_topo_port_entry port_entry[] __counted_by(num_entries); }; #define MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH (0x00) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index dc2cdd5f0311..875bad7538f2 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -57,8 +57,8 @@ extern struct list_head mrioc_list; extern int prot_mask; extern atomic64_t event_counter; -#define MPI3MR_DRIVER_VERSION "8.9.1.0.51" -#define MPI3MR_DRIVER_RELDATE "29-May-2024" +#define MPI3MR_DRIVER_VERSION "8.10.0.5.50" +#define MPI3MR_DRIVER_RELDATE "08-Aug-2024" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL" @@ -213,6 +213,7 @@ extern atomic64_t event_counter; #define MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_INDEX 0 #define MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_DATA 1 +#define MPI3MR_THRESHOLD_REPLY_COUNT 100 /* SGE Flag definition */ #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 8b0eded6ef36..01f035f9330e 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -100,7 +100,8 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc) dprint_init(mrioc, "trying to allocate trace diag buffer of size = %dKB\n", trace_size / 1024); - if (mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { + if (get_order(trace_size) > MAX_PAGE_ORDER || + mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { retry = true; trace_size -= trace_dec_size; dprint_init(mrioc, "trace diag buffer allocation failed\n" @@ -118,8 +119,12 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc) diag_buffer->type = MPI3_DIAG_BUFFER_TYPE_FW; diag_buffer->status = MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED; if ((mrioc->facts.diag_fw_sz < fw_size) && (fw_size >= fw_min_size)) { - diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, - fw_size, &diag_buffer->dma_addr, GFP_KERNEL); + if (get_order(fw_size) <= MAX_PAGE_ORDER) { + diag_buffer->addr + = dma_alloc_coherent(&mrioc->pdev->dev, fw_size, + &diag_buffer->dma_addr, + GFP_KERNEL); + } if (!retry) dprint_init(mrioc, "%s:trying to allocate firmware diag buffer of size = %dKB\n", diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index c196dc14ad20..6eb5bcd8e757 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -345,6 +345,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, { u16 reply_desc_type, host_tag = 0; u16 ioc_status = MPI3_IOCSTATUS_SUCCESS; + u16 masked_ioc_status = MPI3_IOCSTATUS_SUCCESS; u32 ioc_loginfo = 0, sense_count = 0; struct mpi3_status_reply_descriptor *status_desc; struct mpi3_address_reply_descriptor *addr_desc; @@ -366,8 +367,8 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, if (ioc_status & MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info); - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; - mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); + masked_ioc_status = ioc_status & MPI3_IOCSTATUS_STATUS_MASK; + mpi3mr_reply_trigger(mrioc, masked_ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc; @@ -380,7 +381,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, if (ioc_status & MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) ioc_loginfo = le32_to_cpu(def_reply->ioc_log_info); - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + masked_ioc_status = ioc_status & MPI3_IOCSTATUS_STATUS_MASK; if (def_reply->function == MPI3_FUNCTION_SCSI_IO) { scsi_reply = (struct mpi3_scsi_io_reply *)def_reply; sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc, @@ -393,7 +394,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, sshdr.asc, sshdr.ascq); } } - mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); + mpi3mr_reply_trigger(mrioc, masked_ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: success_desc = (struct mpi3_success_reply_descriptor *)reply_desc; @@ -408,7 +409,10 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, if (cmdptr->state & MPI3MR_CMD_PENDING) { cmdptr->state |= MPI3MR_CMD_COMPLETE; cmdptr->ioc_loginfo = ioc_loginfo; - cmdptr->ioc_status = ioc_status; + if (host_tag == MPI3MR_HOSTTAG_BSG_CMDS) + cmdptr->ioc_status = ioc_status; + else + cmdptr->ioc_status = masked_ioc_status; cmdptr->state &= ~MPI3MR_CMD_PENDING; if (def_reply) { cmdptr->state |= MPI3MR_CMD_REPLY_VALID; @@ -439,6 +443,7 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) u32 admin_reply_ci = mrioc->admin_reply_ci; u32 num_admin_replies = 0; u64 reply_dma = 0; + u16 threshold_comps = 0; struct mpi3_default_reply_descriptor *reply_desc; if (!atomic_add_unless(&mrioc->admin_reply_q_in_use, 1, 1)) @@ -462,6 +467,7 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) if (reply_dma) mpi3mr_repost_reply_buf(mrioc, reply_dma); num_admin_replies++; + threshold_comps++; if (++admin_reply_ci == mrioc->num_admin_replies) { admin_reply_ci = 0; exp_phase ^= 1; @@ -472,6 +478,11 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) if ((le16_to_cpu(reply_desc->reply_flags) & MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) break; + if (threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { + writel(admin_reply_ci, + &mrioc->sysif_regs->admin_reply_queue_ci); + threshold_comps = 0; + } } while (1); writel(admin_reply_ci, &mrioc->sysif_regs->admin_reply_queue_ci); @@ -525,7 +536,7 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, u32 num_op_reply = 0; u64 reply_dma = 0; struct mpi3_default_reply_descriptor *reply_desc; - u16 req_q_idx = 0, reply_qidx; + u16 req_q_idx = 0, reply_qidx, threshold_comps = 0; reply_qidx = op_reply_q->qid - 1; @@ -556,6 +567,7 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, if (reply_dma) mpi3mr_repost_reply_buf(mrioc, reply_dma); num_op_reply++; + threshold_comps++; if (++reply_ci == op_reply_q->num_replies) { reply_ci = 0; @@ -577,13 +589,19 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, break; } #endif + if (threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { + writel(reply_ci, + &mrioc->sysif_regs->oper_queue_indexes[reply_qidx].consumer_index); + atomic_sub(threshold_comps, &op_reply_q->pend_ios); + threshold_comps = 0; + } } while (1); writel(reply_ci, &mrioc->sysif_regs->oper_queue_indexes[reply_qidx].consumer_index); op_reply_q->ci = reply_ci; op_reply_q->ephase = exp_phase; - + atomic_sub(threshold_comps, &op_reply_q->pend_ios); atomic_dec(&op_reply_q->in_use); return num_op_reply; } diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 69b14918de59..616894571c6a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -3575,6 +3575,17 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, scmd->sc_data_direction); priv->meta_sg_valid = 1; /* To unmap meta sg DMA */ } else { + /* + * Some firmware versions byte-swap the REPORT ZONES command + * reply from ATA-ZAC devices by directly accessing in the host + * buffer. This does not respect the default command DMA + * direction and causes IOMMU page faults on some architectures + * with an IOMMU enforcing write mappings (e.g. AMD hosts). + * Avoid such issue by making the REPORT ZONES buffer mapping + * bi-directional. + */ + if (scmd->cmnd[0] == ZBC_IN && scmd->cmnd[1] == ZI_REPORT_ZONES) + scmd->sc_data_direction = DMA_BIDIRECTIONAL; sg_scmd = scsi_sglist(scmd); sges_left = scsi_dma_map(scmd); } @@ -5223,6 +5234,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&mrioc->watchdog_lock); spin_lock_init(&mrioc->chain_buf_lock); spin_lock_init(&mrioc->sas_node_lock); + spin_lock_init(&mrioc->trigger_lock); INIT_LIST_HEAD(&mrioc->fwevt_list); INIT_LIST_HEAD(&mrioc->tgtdev_list); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index b2bcf4a27ddc..b785a7e88b49 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2671,6 +2671,22 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1); } +static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd) +{ + /* + * Some firmware versions byte-swap the REPORT ZONES command reply from + * ATA-ZAC devices by directly accessing in the host buffer. This does + * not respect the default command DMA direction and causes IOMMU page + * faults on some architectures with an IOMMU enforcing write mappings + * (e.g. AMD hosts). Avoid such issue by making the report zones buffer + * mapping bi-directional. + */ + if (cmd->cmnd[0] == ZBC_IN && cmd->cmnd[1] == ZI_REPORT_ZONES) + cmd->sc_data_direction = DMA_BIDIRECTIONAL; + + return scsi_dma_map(cmd); +} + /** * _base_build_sg_scmd - main sg creation routine * pcie_device is unused here! @@ -2717,7 +2733,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); + sges_left = _base_scsi_dma_map(scmd); if (sges_left < 0) return -ENOMEM; @@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, } sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); + sges_left = _base_scsi_dma_map(scmd); if (sges_left < 0) return -ENOMEM; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index adeaa8ab9951..194f9679c512 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1382,7 +1382,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks, protect | fua, dld); - } else if (rq->cmd_flags & REQ_ATOMIC && write) { + } else if (rq->cmd_flags & REQ_ATOMIC) { ret = sd_setup_atomic_cmnd(cmd, lba, nr_blocks, sdkp->use_atomic_write_boundary, protect | fua); @@ -2711,8 +2711,6 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, if (buffer[14] & 0x40) /* LBPRZ */ sdkp->lbprz = 1; - - sd_config_discard(sdkp, lim, SD_LBP_WS16); } sdkp->capacity = lba + 1; @@ -3310,6 +3308,9 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) static unsigned int sd_discard_mode(struct scsi_disk *sdkp) { + if (!sdkp->lbpme) + return SD_LBP_FULL; + if (!sdkp->lbpvpd) { /* LBP VPD page not provided */ if (sdkp->max_unmap_blocks) @@ -3365,8 +3366,6 @@ static void sd_read_block_limits(struct scsi_disk *sdkp, sdkp->unmap_alignment = get_unaligned_be32(&vpd->data[32]) & ~(1 << 31); - sd_config_discard(sdkp, lim, sd_discard_mode(sdkp)); - config_atomic: sdkp->max_atomic = get_unaligned_be32(&vpd->data[44]); sdkp->atomic_alignment = get_unaligned_be32(&vpd->data[48]); @@ -3753,9 +3752,10 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_block_limits_ext(sdkp); sd_read_block_characteristics(sdkp, &lim); sd_zbc_read_zones(sdkp, &lim, buffer); - sd_read_cpr(sdkp); } + sd_config_discard(sdkp, &lim, sd_discard_mode(sdkp)); + sd_print_capacity(sdkp, old_capacity); sd_read_write_protect_flag(sdkp, buffer); @@ -3808,6 +3808,14 @@ static int sd_revalidate_disk(struct gendisk *disk) if (err) return err; + /* + * Query concurrent positioning ranges after + * queue_limits_commit_update() unlocked q->limits_lock to avoid + * deadlock with q->sysfs_dir_lock and q->sysfs_lock. + */ + if (sdkp->media_present && scsi_device_supports_vpd(sdp)) + sd_read_cpr(sdkp); + /* * For a zoned drive, revalidating the zones can be done only once * the gendisk capacity is set. So if this fails, set back the gendisk @@ -4205,6 +4213,8 @@ static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); + if (opal_unlock_from_suspend(sdkp->opal_dev)) { sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n"); return -EIO; @@ -4221,13 +4231,12 @@ static int sd_resume_common(struct device *dev, bool runtime) if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ return 0; - sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - if (!sd_do_start_stop(sdkp->device, runtime)) { sdkp->suspended = false; return 0; } + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); ret = sd_start_stop_device(sdkp, 1); if (!ret) { sd_resume(dev); diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index cdedc271857a..023fbce04e7a 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -1158,7 +1158,7 @@ struct pqi_scsi_dev { struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN]; atomic_t scsi_cmds_outstanding[PQI_MAX_LUNS_PER_DEVICE]; - unsigned int raid_bypass_cnt; + u64 __percpu *raid_bypass_cnt; struct pqi_tmf_work tmf_work[PQI_MAX_LUNS_PER_DEVICE]; }; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 24c7cb285dca..b5396d722d52 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "2.1.26-030" +#define DRIVER_VERSION "2.1.28-025" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 -#define DRIVER_RELEASE 26 -#define DRIVER_REVISION 30 +#define DRIVER_RELEASE 28 +#define DRIVER_REVISION 25 #define DRIVER_NAME "Microchip SmartPQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" @@ -1508,6 +1508,12 @@ static int pqi_get_raid_map(struct pqi_ctrl_info *ctrl_info, if (rc) goto error; + device->raid_bypass_cnt = alloc_percpu(u64); + if (!device->raid_bypass_cnt) { + rc = -ENOMEM; + goto error; + } + device->raid_map = raid_map; return 0; @@ -2099,6 +2105,10 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, /* To prevent this from being freed later. */ new_device->raid_map = NULL; } + if (new_device->raid_bypass_enabled && existing_device->raid_bypass_cnt == NULL) { + existing_device->raid_bypass_cnt = new_device->raid_bypass_cnt; + new_device->raid_bypass_cnt = NULL; + } existing_device->raid_bypass_configured = new_device->raid_bypass_configured; existing_device->raid_bypass_enabled = new_device->raid_bypass_enabled; } @@ -2121,6 +2131,7 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, static inline void pqi_free_device(struct pqi_scsi_dev *device) { if (device) { + free_percpu(device->raid_bypass_cnt); kfree(device->raid_map); kfree(device); } @@ -2354,14 +2365,6 @@ static inline void pqi_mask_device(u8 *scsi3addr) scsi3addr[3] |= 0xc0; } -static inline bool pqi_is_multipath_device(struct pqi_scsi_dev *device) -{ - if (pqi_is_logical_device(device)) - return false; - - return (device->path_map & (device->path_map - 1)) != 0; -} - static inline bool pqi_expose_device(struct pqi_scsi_dev *device) { return !device->is_physical_device || !pqi_skip_device(device->scsi3addr); @@ -3244,6 +3247,20 @@ static void pqi_process_raid_io_error(struct pqi_io_request *io_request) sense_data_length); } + if (pqi_cmd_priv(scmd)->this_residual && + !pqi_is_logical_device(scmd->device->hostdata) && + scsi_status == SAM_STAT_CHECK_CONDITION && + host_byte == DID_OK && + sense_data_length && + scsi_normalize_sense(error_info->data, sense_data_length, &sshdr) && + sshdr.sense_key == ILLEGAL_REQUEST && + sshdr.asc == 0x26 && + sshdr.ascq == 0x0) { + host_byte = DID_NO_CONNECT; + pqi_take_device_offline(scmd->device, "AIO"); + scsi_build_sense_buffer(0, scmd->sense_buffer, HARDWARE_ERROR, 0x3e, 0x1); + } + scmd->result = scsi_status; set_host_byte(scmd, host_byte); } @@ -3258,14 +3275,12 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) int residual_count; int xfer_count; bool device_offline; - struct pqi_scsi_dev *device; scmd = io_request->scmd; error_info = io_request->error_info; host_byte = DID_OK; sense_data_length = 0; device_offline = false; - device = scmd->device->hostdata; switch (error_info->service_response) { case PQI_AIO_SERV_RESPONSE_COMPLETE: @@ -3290,14 +3305,8 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) break; case PQI_AIO_STATUS_AIO_PATH_DISABLED: pqi_aio_path_disabled(io_request); - if (pqi_is_multipath_device(device)) { - pqi_device_remove_start(device); - host_byte = DID_NO_CONNECT; - scsi_status = SAM_STAT_CHECK_CONDITION; - } else { - scsi_status = SAM_STAT_GOOD; - io_request->status = -EAGAIN; - } + scsi_status = SAM_STAT_GOOD; + io_request->status = -EAGAIN; break; case PQI_AIO_STATUS_NO_PATH_TO_DEVICE: case PQI_AIO_STATUS_INVALID_DEVICE: @@ -6007,6 +6016,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm u16 hw_queue; struct pqi_queue_group *queue_group; bool raid_bypassed; + u64 *raid_bypass_cnt; u8 lun; scmd->host_scribble = PQI_NO_COMPLETION; @@ -6025,7 +6035,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm ctrl_info = shost_to_hba(shost); - if (pqi_ctrl_offline(ctrl_info) || pqi_device_in_remove(device)) { + if (pqi_ctrl_offline(ctrl_info) || pqi_device_offline(device) || pqi_device_in_remove(device)) { set_host_byte(scmd, DID_NO_CONNECT); pqi_scsi_done(scmd); return 0; @@ -6053,7 +6063,8 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm rc = pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd, queue_group); if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY) { raid_bypassed = true; - device->raid_bypass_cnt++; + raid_bypass_cnt = per_cpu_ptr(device->raid_bypass_cnt, smp_processor_id()); + (*raid_bypass_cnt)++; } } if (!raid_bypassed) @@ -7350,7 +7361,9 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, struct scsi_device *sdev; struct pqi_scsi_dev *device; unsigned long flags; - unsigned int raid_bypass_cnt; + u64 raid_bypass_cnt; + int cpu; + u64 *per_cpu_bypass_cnt_ptr; sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); @@ -7366,11 +7379,18 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, return -ENODEV; } - raid_bypass_cnt = device->raid_bypass_cnt; + raid_bypass_cnt = 0; + + if (device->raid_bypass_cnt) { + for_each_online_cpu(cpu) { + per_cpu_bypass_cnt_ptr = per_cpu_ptr(device->raid_bypass_cnt, cpu); + raid_bypass_cnt += *per_cpu_bypass_cnt_ptr; + } + } spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); - return scnprintf(buffer, PAGE_SIZE, "0x%x\n", raid_bypass_cnt); + return scnprintf(buffer, PAGE_SIZE, "0x%llx\n", raid_bypass_cnt); } static ssize_t pqi_sas_ncq_prio_enable_show(struct device *dev, @@ -9472,6 +9492,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x193d, 0x110b) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x1110) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x193d, 0x8460) @@ -9588,6 +9612,14 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1bd4, 0x0089) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x00a1) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f3a, 0x0104) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x19e5, 0xd227) @@ -10180,6 +10212,98 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1137, 0x02fa) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0045) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0046) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0047) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0048) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x004a) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x004b) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x004c) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x004f) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0051) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0052) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0053) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0054) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x006b) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x006c) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x006d) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x006f) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0070) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0071) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0072) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0086) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0087) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0088) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1ff9, 0x0089) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1e93, 0x1000) diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index cc824dcfe7da..abc78320c66d 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -873,7 +873,7 @@ snic_global_data_init(void) snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL] = cachep; len = sizeof(struct snic_host_req); - cachep = kmem_cache_create("snic_req_maxsgl", len, SNIC_SG_DESC_ALIGN, + cachep = kmem_cache_create("snic_req_tm", len, SNIC_SG_DESC_ALIGN, SLAB_HWCACHE_ALIGN, NULL); if (!cachep) { SNIC_ERR("Failed to create snic tm req slab\n"); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index f51702893306..fffc0fa52594 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -304,7 +304,7 @@ static int sun3scsi_dma_setup(struct NCR5380_hostdata *hostdata, sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); #endif - return count; + return count; } diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c index e80a32421a8c..fe313800aed0 100644 --- a/drivers/ufs/core/ufs-sysfs.c +++ b/drivers/ufs/core/ufs-sysfs.c @@ -198,6 +198,24 @@ static u32 ufshcd_us_to_ahit(unsigned int timer) FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale); } +static int ufshcd_read_hci_reg(struct ufs_hba *hba, u32 *val, unsigned int reg) +{ + down(&hba->host_sem); + if (!ufshcd_is_user_access_allowed(hba)) { + up(&hba->host_sem); + return -EBUSY; + } + + ufshcd_rpm_get_sync(hba); + ufshcd_hold(hba); + *val = ufshcd_readl(hba, reg); + ufshcd_release(hba); + ufshcd_rpm_put_sync(hba); + + up(&hba->host_sem); + return 0; +} + static ssize_t auto_hibern8_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -208,23 +226,11 @@ static ssize_t auto_hibern8_show(struct device *dev, if (!ufshcd_is_auto_hibern8_supported(hba)) return -EOPNOTSUPP; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - ret = -EBUSY; - goto out; - } - - pm_runtime_get_sync(hba->dev); - ufshcd_hold(hba); - ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); - ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); - - ret = sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit)); + ret = ufshcd_read_hci_reg(hba, &ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); + if (ret) + return ret; -out: - up(&hba->host_sem); - return ret; + return sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit)); } static ssize_t auto_hibern8_store(struct device *dev, @@ -519,6 +525,58 @@ static const struct attribute_group ufs_sysfs_capabilities_group = { .attrs = ufs_sysfs_capabilities_attrs, }; +static ssize_t version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%x\n", hba->ufs_version); +} + +static ssize_t product_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + u32 val; + struct ufs_hba *hba = dev_get_drvdata(dev); + + ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_PID); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", val); +} + +static ssize_t man_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + u32 val; + struct ufs_hba *hba = dev_get_drvdata(dev); + + ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_MID); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", val); +} + +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RO(product_id); +static DEVICE_ATTR_RO(man_id); + +static struct attribute *ufs_sysfs_ufshci_cap_attrs[] = { + &dev_attr_version.attr, + &dev_attr_product_id.attr, + &dev_attr_man_id.attr, + NULL +}; + +static const struct attribute_group ufs_sysfs_ufshci_group = { + .name = "ufshci_capabilities", + .attrs = ufs_sysfs_ufshci_cap_attrs, +}; + static ssize_t monitor_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1502,6 +1560,7 @@ static const struct attribute_group ufs_sysfs_attributes_group = { static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_capabilities_group, + &ufs_sysfs_ufshci_group, &ufs_sysfs_monitor_group, &ufs_sysfs_power_info_group, &ufs_sysfs_device_descriptor_group, diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index ce36154ce963..7aea8fbaeee8 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -316,6 +316,11 @@ static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba) return pm_runtime_get_sync(&hba->ufs_device_wlun->sdev_gendev); } +static inline int ufshcd_rpm_get_if_active(struct ufs_hba *hba) +{ + return pm_runtime_get_if_active(&hba->ufs_device_wlun->sdev_gendev); +} + static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba) { return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index dc757ba47522..6ccff001d486 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -51,8 +51,10 @@ /* UIC command timeout, unit: ms */ -#define UIC_CMD_TIMEOUT 500 - +enum { + UIC_CMD_TIMEOUT_DEFAULT = 500, + UIC_CMD_TIMEOUT_MAX = 2000, +}; /* NOP OUT retries waiting for NOP IN response */ #define NOP_OUT_RETRIES 10 /* Timeout after 50 msecs if NOP OUT hangs without response */ @@ -116,6 +118,23 @@ static bool is_mcq_supported(struct ufs_hba *hba) module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); +static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT; + +static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp) +{ + return param_set_uint_minmax(val, kp, UIC_CMD_TIMEOUT_DEFAULT, + UIC_CMD_TIMEOUT_MAX); +} + +static const struct kernel_param_ops uic_cmd_timeout_ops = { + .set = uic_cmd_timeout_set, + .get = param_get_uint, +}; + +module_param_cb(uic_cmd_timeout, &uic_cmd_timeout_ops, &uic_cmd_timeout, 0644); +MODULE_PARM_DESC(uic_cmd_timeout, + "UFS UIC command timeout in milliseconds. Defaults to 500ms. Supported values range from 500ms to 2 seconds inclusively"); + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -2416,7 +2435,21 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) return err; } + /* + * The UFSHCI 3.0 specification does not define MCQ_SUPPORT and + * LSDB_SUPPORT, but [31:29] as reserved bits with reset value 0s, which + * means we can simply read values regardless of version. + */ hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities); + /* + * 0h: legacy single doorbell support is available + * 1h: indicate that legacy single doorbell support has been removed + */ + if (!(hba->quirks & UFSHCD_QUIRK_BROKEN_LSDBS_CAP)) + hba->lsdb_sup = !FIELD_GET(MASK_LSDB_SUPPORT, hba->capabilities); + else + hba->lsdb_sup = true; + if (!hba->mcq_sup) return 0; @@ -2438,7 +2471,7 @@ static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba) { u32 val; int ret = read_poll_timeout(ufshcd_readl, val, val & UIC_COMMAND_READY, - 500, UIC_CMD_TIMEOUT * 1000, false, hba, + 500, uic_cmd_timeout * 1000, false, hba, REG_CONTROLLER_STATUS); return ret == 0; } @@ -2498,7 +2531,7 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) lockdep_assert_held(&hba->uic_cmd_mutex); if (wait_for_completion_timeout(&uic_cmd->done, - msecs_to_jiffies(UIC_CMD_TIMEOUT))) { + msecs_to_jiffies(uic_cmd_timeout))) { ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT; } else { ret = -ETIMEDOUT; @@ -4090,11 +4123,16 @@ static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) min_sleep_time_us = MIN_DELAY_BEFORE_DME_CMDS_US - delta; else - return; /* no more delay required */ + min_sleep_time_us = 0; /* no more delay required */ + } + + if (min_sleep_time_us > 0) { + /* allow sleep for extra 50us if needed */ + usleep_range(min_sleep_time_us, min_sleep_time_us + 50); } - /* allow sleep for extra 50us if needed */ - usleep_range(min_sleep_time_us, min_sleep_time_us + 50); + /* update the last_dme_cmd_tstamp */ + hba->last_dme_cmd_tstamp = ktime_get(); } /** @@ -4266,7 +4304,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) } if (!wait_for_completion_timeout(hba->uic_async_done, - msecs_to_jiffies(UIC_CMD_TIMEOUT))) { + msecs_to_jiffies(uic_cmd_timeout))) { dev_err(hba->dev, "pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n", cmd->command, cmd->argument3); @@ -6553,7 +6591,8 @@ static void ufshcd_err_handler(struct work_struct *work) if (ufshcd_err_handling_should_stop(hba)) goto skip_err_handling; - if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { + if ((hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) && + !hba->force_reset) { bool ret; spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -8211,7 +8250,10 @@ static void ufshcd_update_rtc(struct ufs_hba *hba) */ val = ts64.tv_sec - hba->dev_info.rtc_time_baseline; - ufshcd_rpm_get_sync(hba); + /* Skip update RTC if RPM state is not RPM_ACTIVE */ + if (ufshcd_rpm_get_if_active(hba) <= 0) + return; + err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, &val); ufshcd_rpm_put_sync(hba); @@ -10265,9 +10307,6 @@ int ufshcd_system_restore(struct device *dev) */ ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H); - /* Resuming from hibernate, assume that link was OFF */ - ufshcd_set_link_off(hba); - return 0; } @@ -10496,6 +10535,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } if (!is_mcq_supported(hba)) { + if (!hba->lsdb_sup) { + dev_err(hba->dev, "%s: failed to initialize (legacy doorbell mode not supported)\n", + __func__); + err = -EINVAL; + goto out_disable; + } err = scsi_add_host(host, hba->dev); if (err) { dev_err(hba->dev, "scsi_add_host failed\n"); diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 16ad3528d80b..9ec318ef52bf 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1293,6 +1293,9 @@ static void exynos_ufs_fmp_resume(struct ufs_hba *hba) { struct arm_smccc_res res; + if (!(hba->caps & UFSHCD_CAP_CRYPTO)) + return; + arm_smccc_smc(SMC_CMD_FMP_SECURITY, 0, SMU_EMBEDDED, CFG_DESCTYPE_3, 0, 0, 0, 0, &res); if (res.a0) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 810e637047d0..c87fdc849c62 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -857,6 +857,9 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) if (host->hw_ver.major > 0x3) hba->quirks |= UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH; + + if (of_device_is_compatible(hba->dev->of_node, "qcom,sm8550-ufshc")) + hba->quirks |= UFSHCD_QUIRK_BROKEN_LSDBS_CAP; } static void ufs_qcom_set_phy_gear(struct ufs_qcom_host *host) @@ -1847,7 +1850,8 @@ static void ufs_qcom_remove(struct platform_device *pdev) } static const struct of_device_id ufs_qcom_of_match[] __maybe_unused = { - { .compatible = "qcom,ufshc"}, + { .compatible = "qcom,ufshc" }, + { .compatible = "qcom,sm8550-ufshc" }, {}, }; MODULE_DEVICE_TABLE(of, ufs_qcom_of_match); diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index a3e69ecafd27..0c9b303ccfa0 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -31,7 +31,6 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) const char *name; u32 *clkfreq = NULL; struct ufs_clk_info *clki; - int len = 0; size_t sz = 0; if (!np) @@ -50,15 +49,12 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) if (cnt <= 0) goto out; - if (!of_get_property(np, "freq-table-hz", &len)) { + sz = of_property_count_u32_elems(np, "freq-table-hz"); + if (sz <= 0) { dev_info(dev, "freq-table-hz property not specified\n"); goto out; } - if (len <= 0) - goto out; - - sz = len / sizeof(*clkfreq); if (sz != 2 * cnt) { dev_err(dev, "%s len mismatch\n", "freq-table-hz"); ret = -EINVAL; @@ -272,10 +268,10 @@ static int ufshcd_parse_operating_points(struct ufs_hba *hba) const char **clk_names; int cnt, i, ret; - if (!of_find_property(np, "operating-points-v2", NULL)) + if (!of_property_present(np, "operating-points-v2")) return 0; - if (of_find_property(np, "freq-table-hz", NULL)) { + if (of_property_present(np, "freq-table-hz")) { dev_err(dev, "%s: operating-points and freq-table-hz are incompatible\n", __func__); return -EINVAL; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 45c40d200154..8ecfb94049db 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -234,7 +234,7 @@ static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd) static inline unsigned int scsi_logical_block_count(struct scsi_cmnd *scmd) { - unsigned int shift = ilog2(scmd->device->sector_size) - SECTOR_SHIFT; + unsigned int shift = ilog2(scmd->device->sector_size); return blk_rq_bytes(scsi_cmd_to_rq(scmd)) >> shift; } diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index a43b14276bc3..0fd2aebac728 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -676,6 +676,14 @@ enum ufshcd_quirks { * the standard best practice for managing keys). */ UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 24, + + /* + * This quirk indicates that the controller reports the value 1 (not + * supported) in the Legacy Single DoorBell Support (LSDBS) bit of the + * Controller Capabilities register although it supports the legacy + * single doorbell mode. + */ + UFSHCD_QUIRK_BROKEN_LSDBS_CAP = 1 << 25, }; enum ufshcd_caps { @@ -1109,6 +1117,7 @@ struct ufs_hba { bool ext_iid_sup; bool scsi_host_added; bool mcq_sup; + bool lsdb_sup; bool mcq_enabled; struct ufshcd_res_info res[RES_MAX]; void __iomem *mcq_base; diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index 38fe97971a65..27364c4a6ef9 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -25,8 +25,9 @@ enum { REG_CONTROLLER_CAPABILITIES = 0x00, REG_MCQCAP = 0x04, REG_UFS_VERSION = 0x08, - REG_CONTROLLER_DEV_ID = 0x10, - REG_CONTROLLER_PROD_ID = 0x14, + REG_EXT_CONTROLLER_CAPABILITIES = 0x0C, + REG_CONTROLLER_PID = 0x10, + REG_CONTROLLER_MID = 0x14, REG_AUTO_HIBERNATE_IDLE_TIMER = 0x18, REG_INTERRUPT_STATUS = 0x20, REG_INTERRUPT_ENABLE = 0x24, @@ -77,6 +78,7 @@ enum { MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, MASK_CRYPTO_SUPPORT = 0x10000000, + MASK_LSDB_SUPPORT = 0x20000000, MASK_MCQ_SUPPORT = 0x40000000, };