mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
Merge branch 7.1/scsi-fixes into 7.2/scsi-staging
Pull in outstanding commits from 7.1 branch. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
#define TPGS_MODE_EXPLICIT 0x2
|
||||
|
||||
#define ALUA_RTPG_SIZE 128
|
||||
#define ALUA_FAILOVER_TIMEOUT 60
|
||||
#define ALUA_FAILOVER_TIMEOUT 255 /* max 255 (8-bit value) */
|
||||
#define ALUA_FAILOVER_RETRIES 5
|
||||
#define ALUA_RTPG_DELAY_MSECS 5
|
||||
#define ALUA_RTPG_RETRY_DELAY 2
|
||||
|
||||
@@ -1385,7 +1385,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
|
||||
|
||||
while (rlen >= sizeof(*desc)) {
|
||||
dlen = desc->fip_dlen * FIP_BPW;
|
||||
if (dlen > rlen)
|
||||
if (dlen < sizeof(*desc) || dlen > rlen)
|
||||
goto err;
|
||||
/* Drop CVL if there are duplicate critical descriptors */
|
||||
if ((desc->fip_dtype < 32) &&
|
||||
|
||||
@@ -1491,7 +1491,7 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
|
||||
phy_id = device->phy->identify.phy_identifier;
|
||||
hdr->dw0 |= cpu_to_le32((1U << phy_id)
|
||||
<< CMD_HDR_PHY_ID_OFF);
|
||||
hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
|
||||
hdr->dw0 |= cpu_to_le32(CMD_HDR_FORCE_PHY_MSK);
|
||||
hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF);
|
||||
}
|
||||
|
||||
|
||||
@@ -1252,6 +1252,9 @@ void isci_host_deinit(struct isci_host *ihost)
|
||||
|
||||
wait_for_stop(ihost);
|
||||
|
||||
/* No further IRQ-driven scheduling can happen past wait_for_stop(). */
|
||||
tasklet_kill(&ihost->completion_tasklet);
|
||||
|
||||
/* phy stop is after controller stop to allow port and device to
|
||||
* go idle before shutting down the phys, but the expectation is
|
||||
* that i/o has been shut off well before we reach this
|
||||
|
||||
@@ -3612,6 +3612,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
|
||||
complete(&cmd_fusion->done);
|
||||
break;
|
||||
case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/
|
||||
/*
|
||||
* Firmware can send stale/duplicate completions for
|
||||
* commands already returned to the pool. scmd_local
|
||||
* would be NULL for such cases. Skip processing to
|
||||
* avoid NULL pointer access.
|
||||
*/
|
||||
if (!scmd_local)
|
||||
break;
|
||||
|
||||
/* Update load balancing info */
|
||||
if (fusion->load_balance_info &&
|
||||
(megasas_priv(cmd_fusion->scmd)->status &
|
||||
|
||||
@@ -2738,8 +2738,20 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
|
||||
pcie_device->enclosure_level,
|
||||
pcie_device->connector_name);
|
||||
|
||||
/*
|
||||
* The HBA firmware passes the NVMe drive's MDTS
|
||||
* (Maximum Data Transfer Size) up to the driver. However,
|
||||
* the driver hardcodes a 4K buffer size for the PRP list,
|
||||
* accommodating at most 512 entries. This strictly limits
|
||||
* the maximum supported NVMe I/O transfer to 2 MiB.
|
||||
*
|
||||
* Cap max_hw_sectors to the smaller of the drive's reported
|
||||
* MDTS or the 2 MiB driver limit to prevent kernel oopses.
|
||||
*/
|
||||
lim->max_hw_sectors = SZ_2M >> SECTOR_SHIFT;
|
||||
if (pcie_device->nvme_mdts)
|
||||
lim->max_hw_sectors = pcie_device->nvme_mdts / 512;
|
||||
lim->max_hw_sectors = min(lim->max_hw_sectors,
|
||||
pcie_device->nvme_mdts >> SECTOR_SHIFT);
|
||||
|
||||
pcie_device_put(pcie_device);
|
||||
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
|
||||
|
||||
@@ -657,7 +657,7 @@ struct pmcraid_hostrcb {
|
||||
*/
|
||||
struct pmcraid_instance {
|
||||
/* Array of allowed-to-be-exposed resources, initialized from
|
||||
* Configutation Table, later updated with CCNs
|
||||
* Configuration Table, later updated with CCNs
|
||||
*/
|
||||
struct pmcraid_resource_entry *res_entries;
|
||||
|
||||
|
||||
@@ -6945,7 +6945,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt)
|
||||
++num_dev_resets;
|
||||
|
||||
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
|
||||
sdev_printk(KERN_INFO, sdp, "doing device reset");
|
||||
sdev_printk(KERN_INFO, sdp, "doing device reset\n");
|
||||
|
||||
scsi_debug_stop_all_queued(sdp);
|
||||
if (devip) {
|
||||
|
||||
@@ -218,7 +218,8 @@ static struct {
|
||||
{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
|
||||
{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
|
||||
{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
|
||||
{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
|
||||
{"Promise", "VTrak E310", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
|
||||
{"Promise", "VTrak E610", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
|
||||
{"Promise", "", NULL, BLIST_SPARSELUN},
|
||||
{"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
|
||||
{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
|
||||
|
||||
@@ -575,10 +575,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
|
||||
|
||||
void scsi_run_host_queues(struct Scsi_Host *shost)
|
||||
{
|
||||
struct scsi_device *sdev;
|
||||
struct scsi_device *sdev, *prev = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
shost_for_each_device(sdev, shost)
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
__shost_for_each_device(sdev, shost) {
|
||||
/*
|
||||
* Only skip devices so deep into removal they will never need
|
||||
* another kick to their queues. Thus scsi_device_get() cannot
|
||||
* be used as it would skip devices in SDEV_CANCEL state which
|
||||
* may need a queue kick.
|
||||
*/
|
||||
if (sdev->sdev_state == SDEV_DEL ||
|
||||
!get_device(&sdev->sdev_gendev))
|
||||
continue;
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
if (prev)
|
||||
put_device(&prev->sdev_gendev);
|
||||
scsi_run_queue(sdev->request_queue);
|
||||
|
||||
prev = sdev;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
if (prev)
|
||||
put_device(&prev->sdev_gendev);
|
||||
}
|
||||
|
||||
static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
|
||||
|
||||
@@ -737,6 +737,37 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fc_fpin_pname_stats_update(struct Scsi_Host *shost,
|
||||
struct fc_rport *attach_rport, u16 event_type,
|
||||
u32 desc_len, u32 fixed_len, u32 pname_count,
|
||||
__be64 *pname_list,
|
||||
void (*stats_update)(u16 event_type,
|
||||
struct fc_fpin_stats *stats))
|
||||
{
|
||||
u32 i;
|
||||
struct fc_rport *rport;
|
||||
u64 wwpn;
|
||||
|
||||
if (desc_len < fixed_len)
|
||||
pname_count = 0;
|
||||
else
|
||||
pname_count = min(pname_count, (desc_len - fixed_len) /
|
||||
sizeof(pname_list[0]));
|
||||
|
||||
for (i = 0; i < pname_count; i++) {
|
||||
wwpn = be64_to_cpu(pname_list[i]);
|
||||
rport = fc_find_rport_by_wwpn(shost, wwpn);
|
||||
if (rport &&
|
||||
(rport->roles & FC_PORT_ROLE_FCP_TARGET ||
|
||||
rport->roles & FC_PORT_ROLE_NVME_TARGET)) {
|
||||
if (rport == attach_rport)
|
||||
continue;
|
||||
stats_update(event_type, &rport->fpin_stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fc_fpin_li_stats_update - routine to update Link Integrity
|
||||
* event statistics.
|
||||
@@ -747,13 +778,11 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)
|
||||
static void
|
||||
fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
|
||||
{
|
||||
u8 i;
|
||||
struct fc_rport *rport = NULL;
|
||||
struct fc_rport *attach_rport = NULL;
|
||||
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
|
||||
struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
|
||||
u16 event_type = be16_to_cpu(li_desc->event_type);
|
||||
u64 wwpn;
|
||||
|
||||
rport = fc_find_rport_by_wwpn(shost,
|
||||
be64_to_cpu(li_desc->attached_wwpn));
|
||||
@@ -764,22 +793,11 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
|
||||
fc_li_stats_update(event_type, &attach_rport->fpin_stats);
|
||||
}
|
||||
|
||||
if (be32_to_cpu(li_desc->pname_count) > 0) {
|
||||
for (i = 0;
|
||||
i < be32_to_cpu(li_desc->pname_count);
|
||||
i++) {
|
||||
wwpn = be64_to_cpu(li_desc->pname_list[i]);
|
||||
rport = fc_find_rport_by_wwpn(shost, wwpn);
|
||||
if (rport &&
|
||||
(rport->roles & FC_PORT_ROLE_FCP_TARGET ||
|
||||
rport->roles & FC_PORT_ROLE_NVME_TARGET)) {
|
||||
if (rport == attach_rport)
|
||||
continue;
|
||||
fc_li_stats_update(event_type,
|
||||
&rport->fpin_stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
fc_fpin_pname_stats_update(shost, attach_rport, event_type,
|
||||
be32_to_cpu(li_desc->desc_len),
|
||||
FC_TLV_DESC_LENGTH_FROM_SZ(*li_desc),
|
||||
be32_to_cpu(li_desc->pname_count),
|
||||
li_desc->pname_list, fc_li_stats_update);
|
||||
|
||||
if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn))
|
||||
fc_li_stats_update(event_type, &fc_host->fpin_stats);
|
||||
@@ -827,13 +845,11 @@ static void
|
||||
fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
|
||||
struct fc_tlv_desc *tlv)
|
||||
{
|
||||
u8 i;
|
||||
struct fc_rport *rport = NULL;
|
||||
struct fc_rport *attach_rport = NULL;
|
||||
struct fc_fn_peer_congn_desc *pc_desc =
|
||||
(struct fc_fn_peer_congn_desc *)tlv;
|
||||
u16 event_type = be16_to_cpu(pc_desc->event_type);
|
||||
u64 wwpn;
|
||||
|
||||
rport = fc_find_rport_by_wwpn(shost,
|
||||
be64_to_cpu(pc_desc->attached_wwpn));
|
||||
@@ -844,22 +860,11 @@ fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
|
||||
fc_cn_stats_update(event_type, &attach_rport->fpin_stats);
|
||||
}
|
||||
|
||||
if (be32_to_cpu(pc_desc->pname_count) > 0) {
|
||||
for (i = 0;
|
||||
i < be32_to_cpu(pc_desc->pname_count);
|
||||
i++) {
|
||||
wwpn = be64_to_cpu(pc_desc->pname_list[i]);
|
||||
rport = fc_find_rport_by_wwpn(shost, wwpn);
|
||||
if (rport &&
|
||||
(rport->roles & FC_PORT_ROLE_FCP_TARGET ||
|
||||
rport->roles & FC_PORT_ROLE_NVME_TARGET)) {
|
||||
if (rport == attach_rport)
|
||||
continue;
|
||||
fc_cn_stats_update(event_type,
|
||||
&rport->fpin_stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
fc_fpin_pname_stats_update(shost, attach_rport, event_type,
|
||||
be32_to_cpu(pc_desc->desc_len),
|
||||
FC_TLV_DESC_LENGTH_FROM_SZ(*pc_desc),
|
||||
be32_to_cpu(pc_desc->pname_count),
|
||||
pc_desc->pname_list, fc_cn_stats_update);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2476,8 +2476,7 @@ sd_spinup_disk(struct scsi_disk *sdkp)
|
||||
{
|
||||
static const u8 cmd[10] = { TEST_UNIT_READY };
|
||||
unsigned long spintime_expire = 0;
|
||||
int spintime, sense_valid = 0;
|
||||
unsigned int the_result;
|
||||
int the_result, spintime, sense_valid = 0;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
struct scsi_failure failure_defs[] = {
|
||||
/* Do not retry Medium Not Present */
|
||||
|
||||
@@ -1801,7 +1801,7 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
|
||||
}
|
||||
|
||||
res = blk_rq_map_user_io(rq, md, hp->dxferp, hp->dxfer_len,
|
||||
GFP_ATOMIC, iov_count, iov_count, 1, rw);
|
||||
GFP_KERNEL, iov_count, iov_count, 1, rw);
|
||||
if (!res) {
|
||||
srp->bio = rq->bio;
|
||||
|
||||
|
||||
@@ -9427,6 +9427,7 @@ static void pqi_shutdown(struct pci_dev *pci_dev)
|
||||
|
||||
pqi_crash_if_pending_command(ctrl_info);
|
||||
pqi_reset(ctrl_info);
|
||||
pqi_ctrl_unblock_device_reset(ctrl_info);
|
||||
}
|
||||
|
||||
static void pqi_process_lockup_action_param(void)
|
||||
|
||||
@@ -995,6 +995,7 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
int data_direction, payload_length;
|
||||
struct iscsi_ecdb_ahdr *ecdb_ahdr;
|
||||
struct iscsi_scsi_req *hdr;
|
||||
u16 ahslength, cdb_length;
|
||||
int iscsi_task_attr;
|
||||
unsigned char *cdb;
|
||||
int sam_task_attr;
|
||||
@@ -1108,14 +1109,27 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
ISCSI_REASON_CMD_NOT_SUPPORTED, buf);
|
||||
}
|
||||
|
||||
cdb = kmalloc(be16_to_cpu(ecdb_ahdr->ahslength) + 15,
|
||||
GFP_KERNEL);
|
||||
ahslength = be16_to_cpu(ecdb_ahdr->ahslength);
|
||||
if (!ahslength) {
|
||||
pr_err("Extended CDB AHS with zero length, protocol error.\n");
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
}
|
||||
if (ahslength > (hdr->hlength * 4) - 3) {
|
||||
pr_err("Extended CDB AHS length %u exceeds available PDU buffer.\n",
|
||||
ahslength);
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
}
|
||||
|
||||
cdb_length = ahslength - 1 + ISCSI_CDB_SIZE;
|
||||
|
||||
cdb = kmalloc(cdb_length, GFP_KERNEL);
|
||||
if (cdb == NULL)
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
||||
memcpy(cdb, hdr->cdb, ISCSI_CDB_SIZE);
|
||||
memcpy(cdb + ISCSI_CDB_SIZE, ecdb_ahdr->ecdb,
|
||||
be16_to_cpu(ecdb_ahdr->ahslength) - 1);
|
||||
memcpy(cdb + ISCSI_CDB_SIZE, ecdb_ahdr->ecdb, cdb_length - ISCSI_CDB_SIZE);
|
||||
}
|
||||
|
||||
data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
|
||||
@@ -2281,7 +2295,9 @@ iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
goto reject;
|
||||
|
||||
if (conn->conn_ops->DataDigest) {
|
||||
data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL);
|
||||
data_crc = iscsit_crc_buf(text_in,
|
||||
ALIGN(payload_length, 4),
|
||||
0, NULL);
|
||||
if (checksum != data_crc) {
|
||||
pr_err("Text data CRC32C DataDigest"
|
||||
" 0x%08x does not match computed"
|
||||
@@ -2300,6 +2316,7 @@ iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
" Command CmdSN: 0x%08x due to"
|
||||
" DataCRC error.\n", hdr->cmdsn);
|
||||
kfree(text_in);
|
||||
cmd->text_in_ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/utils.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/err.h>
|
||||
@@ -340,13 +341,22 @@ static int chap_server_compute_hash(
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
case BASE64: {
|
||||
size_t r_len = strlen(chap_r);
|
||||
|
||||
while (r_len > 0 && chap_r[r_len - 1] == '=')
|
||||
r_len--;
|
||||
if (r_len > DIV_ROUND_UP(chap->digest_size * 4, 3)) {
|
||||
pr_err("Malformed CHAP_R: base64 payload too long\n");
|
||||
goto out;
|
||||
}
|
||||
if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) !=
|
||||
chap->digest_size) {
|
||||
pr_err("Malformed CHAP_R: invalid BASE64\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pr_err("Could not find CHAP_R\n");
|
||||
goto out;
|
||||
@@ -399,7 +409,7 @@ static int chap_server_compute_hash(
|
||||
pr_debug("[server] %s Server Digest: %s\n",
|
||||
chap->digest_name, response);
|
||||
|
||||
if (memcmp(server_digest, client_digest, chap->digest_size) != 0) {
|
||||
if (crypto_memneq(server_digest, client_digest, chap->digest_size)) {
|
||||
pr_debug("[server] %s Digests do not match!\n\n",
|
||||
chap->digest_name);
|
||||
goto out;
|
||||
@@ -429,9 +439,11 @@ static int chap_server_compute_hash(
|
||||
}
|
||||
|
||||
if (type == HEX)
|
||||
ret = kstrtoul(&identifier[2], 0, &id);
|
||||
ret = kstrtoul(identifier, 16, &id);
|
||||
else if (type == DECIMAL)
|
||||
ret = kstrtoul(identifier, 10, &id);
|
||||
else
|
||||
ret = kstrtoul(identifier, 0, &id);
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret);
|
||||
@@ -473,6 +485,14 @@ static int chap_server_compute_hash(
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
/*
|
||||
* No overflow check needed: initiatorchg_binhex is
|
||||
* CHAP_CHALLENGE_STR_LEN bytes and extract_param() caps
|
||||
* initiatorchg at CHAP_CHALLENGE_STR_LEN characters, so
|
||||
* the decoded output is at most DIV_ROUND_UP(
|
||||
* (CHAP_CHALLENGE_STR_LEN - 1) * 3, 4) bytes, which is
|
||||
* less than CHAP_CHALLENGE_STR_LEN.
|
||||
*/
|
||||
initiatorchg_len = chap_base64_decode(initiatorchg_binhex,
|
||||
initiatorchg,
|
||||
strlen(initiatorchg));
|
||||
|
||||
@@ -899,10 +899,14 @@ static int iscsi_target_handle_csg_zero(
|
||||
SENDER_TARGET,
|
||||
login->rsp_buf,
|
||||
&login->rsp_length,
|
||||
MAX_KEY_VALUE_PAIRS,
|
||||
conn->param_list,
|
||||
conn->tpg->tpg_attrib.login_keys_workaround);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
|
||||
ISCSI_LOGIN_STATUS_INIT_ERR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!iscsi_check_negotiated_keys(conn->param_list)) {
|
||||
bool auth_required = iscsi_conn_auth_required(conn);
|
||||
@@ -986,6 +990,7 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo
|
||||
SENDER_TARGET,
|
||||
login->rsp_buf,
|
||||
&login->rsp_length,
|
||||
MAX_KEY_VALUE_PAIRS,
|
||||
conn->param_list,
|
||||
conn->tpg->tpg_attrib.login_keys_workaround);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -1371,19 +1371,42 @@ int iscsi_decode_text_input(
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append "key=value" plus a trailing NUL into @textbuf at *@length.
|
||||
* Returns 0 on success and advances *@length, or -EMSGSIZE if the
|
||||
* record (including the NUL) would not fit in the remaining buffer.
|
||||
*/
|
||||
static int iscsi_encode_text_record(char *textbuf, u32 *length,
|
||||
u32 textbuf_size,
|
||||
const char *key, const char *value)
|
||||
{
|
||||
int n;
|
||||
u32 avail;
|
||||
|
||||
if (*length >= textbuf_size)
|
||||
return -EMSGSIZE;
|
||||
|
||||
avail = textbuf_size - *length;
|
||||
n = snprintf(textbuf + *length, avail, "%s=%s", key, value);
|
||||
if (n < 0 || (u32)n + 1 > avail)
|
||||
return -EMSGSIZE;
|
||||
|
||||
*length += n + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsi_encode_text_output(
|
||||
u8 phase,
|
||||
u8 sender,
|
||||
char *textbuf,
|
||||
u32 *length,
|
||||
u32 textbuf_size,
|
||||
struct iscsi_param_list *param_list,
|
||||
bool keys_workaround)
|
||||
{
|
||||
char *output_buf = NULL;
|
||||
struct iscsi_extra_response *er;
|
||||
struct iscsi_param *param;
|
||||
|
||||
output_buf = textbuf + *length;
|
||||
int ret;
|
||||
|
||||
if (iscsi_enforce_integrity_rules(phase, param_list) < 0)
|
||||
return -1;
|
||||
@@ -1395,10 +1418,12 @@ int iscsi_encode_text_output(
|
||||
!IS_PSTATE_RESPONSE_SENT(param) &&
|
||||
!IS_PSTATE_REPLY_OPTIONAL(param) &&
|
||||
(param->phase & phase)) {
|
||||
*length += sprintf(output_buf, "%s=%s",
|
||||
param->name, param->value);
|
||||
*length += 1;
|
||||
output_buf = textbuf + *length;
|
||||
ret = iscsi_encode_text_record(textbuf, length,
|
||||
textbuf_size,
|
||||
param->name,
|
||||
param->value);
|
||||
if (ret < 0)
|
||||
goto err_overflow;
|
||||
SET_PSTATE_RESPONSE_SENT(param);
|
||||
pr_debug("Sending key: %s=%s\n",
|
||||
param->name, param->value);
|
||||
@@ -1408,10 +1433,12 @@ int iscsi_encode_text_output(
|
||||
!IS_PSTATE_ACCEPTOR(param) &&
|
||||
!IS_PSTATE_PROPOSER(param) &&
|
||||
(param->phase & phase)) {
|
||||
*length += sprintf(output_buf, "%s=%s",
|
||||
param->name, param->value);
|
||||
*length += 1;
|
||||
output_buf = textbuf + *length;
|
||||
ret = iscsi_encode_text_record(textbuf, length,
|
||||
textbuf_size,
|
||||
param->name,
|
||||
param->value);
|
||||
if (ret < 0)
|
||||
goto err_overflow;
|
||||
SET_PSTATE_PROPOSER(param);
|
||||
iscsi_check_proposer_for_optional_reply(param,
|
||||
keys_workaround);
|
||||
@@ -1421,14 +1448,21 @@ int iscsi_encode_text_output(
|
||||
}
|
||||
|
||||
list_for_each_entry(er, ¶m_list->extra_response_list, er_list) {
|
||||
*length += sprintf(output_buf, "%s=%s", er->key, er->value);
|
||||
*length += 1;
|
||||
output_buf = textbuf + *length;
|
||||
ret = iscsi_encode_text_record(textbuf, length, textbuf_size,
|
||||
er->key, er->value);
|
||||
if (ret < 0)
|
||||
goto err_overflow;
|
||||
pr_debug("Sending key: %s=%s\n", er->key, er->value);
|
||||
}
|
||||
iscsi_release_extra_responses(param_list);
|
||||
|
||||
return 0;
|
||||
|
||||
err_overflow:
|
||||
pr_err("iSCSI login response buffer (%u bytes) exhausted, dropping login.\n",
|
||||
textbuf_size);
|
||||
iscsi_release_extra_responses(param_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int iscsi_check_negotiated_keys(struct iscsi_param_list *param_list)
|
||||
|
||||
@@ -43,7 +43,7 @@ extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_
|
||||
extern int iscsi_extract_key_value(char *, char **, char **);
|
||||
extern int iscsi_update_param_value(struct iscsi_param *, char *);
|
||||
extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsit_conn *);
|
||||
extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
|
||||
extern int iscsi_encode_text_output(u8, u8, char *, u32 *, u32,
|
||||
struct iscsi_param_list *, bool);
|
||||
extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);
|
||||
extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
|
||||
|
||||
@@ -329,6 +329,7 @@ static int tcm_loop_driver_probe(struct device *dev)
|
||||
if (error) {
|
||||
pr_err("%s: scsi_add_host failed\n", __func__);
|
||||
scsi_host_put(sh);
|
||||
tl_hba->sh = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
@@ -342,8 +343,10 @@ static void tcm_loop_driver_remove(struct device *dev)
|
||||
tl_hba = to_tcm_loop_hba(dev);
|
||||
sh = tl_hba->sh;
|
||||
|
||||
scsi_remove_host(sh);
|
||||
scsi_host_put(sh);
|
||||
if (sh) {
|
||||
scsi_remove_host(sh);
|
||||
scsi_host_put(sh);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcm_loop_release_adapter(struct device *dev)
|
||||
@@ -372,6 +375,11 @@ static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!tl_hba->sh) {
|
||||
device_unregister(&tl_hba->dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3249,7 +3249,7 @@ static ssize_t target_tg_pt_gp_members_show(struct config_item *item,
|
||||
config_item_name(&lun->lun_group.cg_item));
|
||||
cur_len++; /* Extra byte for NULL terminator */
|
||||
|
||||
if ((cur_len + len) > PAGE_SIZE) {
|
||||
if (cur_len > TG_PT_GROUP_NAME_BUF || (cur_len + len) > PAGE_SIZE) {
|
||||
pr_warn("Ran out of lu_gp_show_attr"
|
||||
"_members buffer\n");
|
||||
break;
|
||||
|
||||
@@ -9303,6 +9303,30 @@ static void ufshcd_config_mcq(struct ufs_hba *hba)
|
||||
hba->nutrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_op_mode - get UFS operating mode.
|
||||
* @hba: per-adapter instance
|
||||
*
|
||||
* Use the PA_PWRMODE value to represent the operating mode of UFS.
|
||||
*
|
||||
*/
|
||||
static enum ufs_op_mode ufshcd_get_op_mode(struct ufs_hba *hba)
|
||||
{
|
||||
u32 mode;
|
||||
u8 rx_mode;
|
||||
u8 tx_mode;
|
||||
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &mode);
|
||||
rx_mode = (mode >> PWRMODE_RX_OFFSET) & PWRMODE_MASK;
|
||||
tx_mode = mode & PWRMODE_MASK;
|
||||
|
||||
if ((rx_mode == SLOW_MODE || rx_mode == SLOWAUTO_MODE) &&
|
||||
(tx_mode == SLOW_MODE || tx_mode == SLOWAUTO_MODE))
|
||||
return LS_MODE;
|
||||
|
||||
return HS_MODE;
|
||||
}
|
||||
|
||||
static int ufshcd_post_device_init(struct ufs_hba *hba)
|
||||
{
|
||||
int ret;
|
||||
@@ -9325,11 +9349,13 @@ static int ufshcd_post_device_init(struct ufs_hba *hba)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Set the right value to bRefClkFreq before attempting to
|
||||
* Set the right value to bRefClkFreq in LS_MODE before attempting to
|
||||
* switch to HS gears.
|
||||
*/
|
||||
if (hba->dev_ref_clk_freq != REF_CLK_FREQ_INVAL)
|
||||
if (ufshcd_get_op_mode(hba) == LS_MODE &&
|
||||
hba->dev_ref_clk_freq != REF_CLK_FREQ_INVAL)
|
||||
ufshcd_set_dev_ref_clk(hba);
|
||||
|
||||
/* Gear up to HS gear. */
|
||||
ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info,
|
||||
UFSHCD_PMC_POLICY_DONT_FORCE);
|
||||
|
||||
@@ -333,6 +333,11 @@ enum ufs_eom_eye_mask {
|
||||
#define DME_LocalTC0ReplayTimeOutVal 0xD042
|
||||
#define DME_LocalAFC0ReqTimeOutVal 0xD043
|
||||
|
||||
enum ufs_op_mode {
|
||||
LS_MODE = 1,
|
||||
HS_MODE = 2,
|
||||
};
|
||||
|
||||
/* PA power modes */
|
||||
enum ufs_pa_pwr_mode {
|
||||
FAST_MODE = 1,
|
||||
|
||||
Reference in New Issue
Block a user