1
0
Fork 0

SCSI for-linus on 20140705

This is a set of 13 fixes, a MAINTAINERS update and a sparse update.  The
 fixes are mostly correct value initialisations, avoiding NULL derefs and some
 uninitialised pointer avoidance.
 
 Signed-off-by: James Bottomley <JBottomley@Parallels.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJTuNEhAAoJEDeqqVYsXL0MYC4H/2gpxHA9rELiqPRLJGNjt9v3
 YlGrIwVAAdYLBSgwtkpAYj6oDJtwRmZvP3Saj2n5Lga+32mgFsPjvy+JsM3O41SL
 k5QRlAs10wMbOB/dSoGxFsKdGnig4NolCIe5p0MGQvAbcCvh9z2Tr876ssvSfMCh
 1mh0xmTCIutD7R2f5WjRckA+HZo+qmLLz5ZyogDasI3mSRAHjcZ+j5HdWBQbEsag
 U6lPDR5VpUjGpigwJ+BPWwKTbIAIW1v2TB1YjWSHr5h2QPLBa+hfbyc15S1AjsGb
 9F5/L432yk4UXQUKyKIpCKi8rDCoioM8dt8ofjjTNfNNjDlYRRHKutalef1yOw8=
 =HPXQ
 -----END PGP SIGNATURE-----

Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "This is a set of 13 fixes, a MAINTAINERS update and a sparse update.
  The fixes are mostly correct value initialisations, avoiding NULL
  derefs and some uninitialised pointer avoidance.

  All the patches have been incubated in -next for a few days.  The
  final patch (use the scsi data buffer length to extract transfer size)
  has been rebased to add a cc to stable, but only the commit message
  has changed"

* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  [SCSI] use the scsi data buffer length to extract transfer size
  virtio-scsi: fix various bad behavior on aborted requests
  virtio-scsi: avoid cancelling uninitialized work items
  ibmvscsi: Add memory barriers for send / receive
  ibmvscsi: Abort init sequence during error recovery
  qla2xxx: Fix sparse warning in qla_target.c.
  bnx2fc: Improve stats update mechanism
  bnx2fc: do not scan uninitialized lists in case of error.
  fc: ensure scan_work isn't active when freeing fc_rport
  pm8001: Fix potential null pointer dereference and memory leak.
  MAINTAINERS: Update LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) maintainers Email IDs
  be2iscsi: remove potential junk pointer free
  be2iscsi: add an missing goto in error path
  scsi_error: set DID_TIME_OUT correctly
  scsi_error: fix invalid setting of host byte
hifive-unleashed-5.1
Linus Torvalds 2014-07-06 12:08:30 -07:00
commit 8addf0c713
13 changed files with 86 additions and 43 deletions

View File

@ -5530,10 +5530,11 @@ S: Maintained
F: arch/arm/mach-lpc32xx/ F: arch/arm/mach-lpc32xx/
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
M: Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com> M: Nagalakshmi Nandigama <nagalakshmi.nandigama@avagotech.com>
M: Sreekanth Reddy <Sreekanth.Reddy@lsi.com> M: Praveen Krishnamoorthy <praveen.krishnamoorthy@avagotech.com>
M: support@lsi.com M: Sreekanth Reddy <sreekanth.reddy@avagotech.com>
L: DL-MPTFusionLinux@lsi.com M: Abhijit Mahajan <abhijit.mahajan@avagotech.com>
L: MPT-FusionLinux.pdl@avagotech.com
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
W: http://www.lsilogic.com/support W: http://www.lsilogic.com/support
S: Supported S: Supported

View File

@ -4198,6 +4198,8 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
kfree(phba->ep_array); kfree(phba->ep_array);
phba->ep_array = NULL; phba->ep_array = NULL;
ret = -ENOMEM; ret = -ENOMEM;
goto free_memory;
} }
for (i = 0; i < phba->params.cxns_per_ctrl; i++) { for (i = 0; i < phba->params.cxns_per_ctrl; i++) {

View File

@ -1008,10 +1008,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
BE2_IPV6 : BE2_IPV4 ; BE2_IPV6 : BE2_IPV4 ;
rc = mgmt_get_if_info(phba, ip_type, &if_info); rc = mgmt_get_if_info(phba, ip_type, &if_info);
if (rc) { if (rc)
kfree(if_info);
return rc; return rc;
}
if (boot_proto == ISCSI_BOOTPROTO_DHCP) { if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
if (if_info->dhcp_state) { if (if_info->dhcp_state) {

View File

@ -516,23 +516,17 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
skb_pull(skb, sizeof(struct fcoe_hdr)); skb_pull(skb, sizeof(struct fcoe_hdr));
fr_len = skb->len - sizeof(struct fcoe_crc_eof); fr_len = skb->len - sizeof(struct fcoe_crc_eof);
stats = per_cpu_ptr(lport->stats, get_cpu());
stats->RxFrames++;
stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
fp = (struct fc_frame *)skb; fp = (struct fc_frame *)skb;
fc_frame_init(fp); fc_frame_init(fp);
fr_dev(fp) = lport; fr_dev(fp) = lport;
fr_sof(fp) = hp->fcoe_sof; fr_sof(fp) = hp->fcoe_sof;
if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
fr_eof(fp) = crc_eof.fcoe_eof; fr_eof(fp) = crc_eof.fcoe_eof;
fr_crc(fp) = crc_eof.fcoe_crc32; fr_crc(fp) = crc_eof.fcoe_crc32;
if (pskb_trim(skb, fr_len)) { if (pskb_trim(skb, fr_len)) {
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@ -544,7 +538,6 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
port = lport_priv(vn_port); port = lport_priv(vn_port);
if (!ether_addr_equal(port->data_src_addr, dest_mac)) { if (!ether_addr_equal(port->data_src_addr, dest_mac)) {
BNX2FC_HBA_DBG(lport, "fpma mismatch\n"); BNX2FC_HBA_DBG(lport, "fpma mismatch\n");
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@ -552,7 +545,6 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
fh->fh_type == FC_TYPE_FCP) { fh->fh_type == FC_TYPE_FCP) {
/* Drop FCP data. We dont this in L2 path */ /* Drop FCP data. We dont this in L2 path */
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@ -562,7 +554,6 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
case ELS_LOGO: case ELS_LOGO:
if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
/* drop non-FIP LOGO */ /* drop non-FIP LOGO */
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@ -572,22 +563,23 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) { if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) {
/* Drop incoming ABTS */ /* Drop incoming ABTS */
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
stats = per_cpu_ptr(lport->stats, smp_processor_id());
stats->RxFrames++;
stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
if (le32_to_cpu(fr_crc(fp)) != if (le32_to_cpu(fr_crc(fp)) !=
~crc32(~0, skb->data, fr_len)) { ~crc32(~0, skb->data, fr_len)) {
if (stats->InvalidCRCCount < 5) if (stats->InvalidCRCCount < 5)
printk(KERN_WARNING PFX "dropping frame with " printk(KERN_WARNING PFX "dropping frame with "
"CRC error\n"); "CRC error\n");
stats->InvalidCRCCount++; stats->InvalidCRCCount++;
put_cpu();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
put_cpu();
fc_exch_recv(lport, fp); fc_exch_recv(lport, fp);
} }

View File

@ -282,6 +282,8 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
arr_sz, GFP_KERNEL); arr_sz, GFP_KERNEL);
if (!cmgr->free_list_lock) { if (!cmgr->free_list_lock) {
printk(KERN_ERR PFX "failed to alloc free_list_lock\n"); printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
kfree(cmgr->free_list);
cmgr->free_list = NULL;
goto mem_err; goto mem_err;
} }

View File

@ -185,6 +185,11 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
if (crq->valid & 0x80) { if (crq->valid & 0x80) {
if (++queue->cur == queue->size) if (++queue->cur == queue->size)
queue->cur = 0; queue->cur = 0;
/* Ensure the read of the valid bit occurs before reading any
* other bits of the CRQ entry
*/
rmb();
} else } else
crq = NULL; crq = NULL;
spin_unlock_irqrestore(&queue->lock, flags); spin_unlock_irqrestore(&queue->lock, flags);
@ -203,6 +208,11 @@ static int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
{ {
struct vio_dev *vdev = to_vio_dev(hostdata->dev); struct vio_dev *vdev = to_vio_dev(hostdata->dev);
/*
* Ensure the command buffer is flushed to memory before handing it
* over to the VIOS to prevent it from fetching any stale data.
*/
mb();
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2); return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
} }
@ -797,7 +807,8 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
evt->hostdata->dev); evt->hostdata->dev);
if (evt->cmnd_done) if (evt->cmnd_done)
evt->cmnd_done(evt->cmnd); evt->cmnd_done(evt->cmnd);
} else if (evt->done) } else if (evt->done && evt->crq.format != VIOSRP_MAD_FORMAT &&
evt->iu.srp.login_req.opcode != SRP_LOGIN_REQ)
evt->done(evt); evt->done(evt);
free_event_struct(&evt->hostdata->pool, evt); free_event_struct(&evt->hostdata->pool, evt);
spin_lock_irqsave(hostdata->host->host_lock, flags); spin_lock_irqsave(hostdata->host->host_lock, flags);

View File

@ -677,7 +677,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
* pm8001_get_phy_settings_info : Read phy setting values. * pm8001_get_phy_settings_info : Read phy setting values.
* @pm8001_ha : our hba. * @pm8001_ha : our hba.
*/ */
void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
{ {
#ifdef PM8001_READ_VPD #ifdef PM8001_READ_VPD
@ -691,11 +691,15 @@ void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
payload.offset = 0; payload.offset = 0;
payload.length = 4096; payload.length = 4096;
payload.func_specific = kzalloc(4096, GFP_KERNEL); payload.func_specific = kzalloc(4096, GFP_KERNEL);
if (!payload.func_specific)
return -ENOMEM;
/* Read phy setting values from flash */ /* Read phy setting values from flash */
PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
wait_for_completion(&completion); wait_for_completion(&completion);
pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);
kfree(payload.func_specific);
#endif #endif
return 0;
} }
#ifdef PM8001_USE_MSIX #ifdef PM8001_USE_MSIX
@ -879,8 +883,11 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
pm8001_init_sas_add(pm8001_ha); pm8001_init_sas_add(pm8001_ha);
/* phy setting support for motherboard controller */ /* phy setting support for motherboard controller */
if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 &&
pdev->subsystem_vendor != 0) pdev->subsystem_vendor != 0) {
pm8001_get_phy_settings_info(pm8001_ha); rc = pm8001_get_phy_settings_info(pm8001_ha);
if (rc)
goto err_out_shost;
}
pm8001_post_sas_ha_init(shost, chip); pm8001_post_sas_ha_init(shost, chip);
rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
if (rc) if (rc)

View File

@ -1128,7 +1128,7 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
ctio->u.status1.flags = ctio->u.status1.flags =
__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 |
CTIO7_FLAGS_TERMINATE); CTIO7_FLAGS_TERMINATE);
ctio->u.status1.ox_id = entry->fcp_hdr_le.ox_id; ctio->u.status1.ox_id = cpu_to_le16(entry->fcp_hdr_le.ox_id);
qla2x00_start_iocbs(vha, vha->req); qla2x00_start_iocbs(vha, vha->req);
@ -1262,6 +1262,7 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
{ {
struct atio_from_isp *atio = &mcmd->orig_iocb.atio; struct atio_from_isp *atio = &mcmd->orig_iocb.atio;
struct ctio7_to_24xx *ctio; struct ctio7_to_24xx *ctio;
uint16_t temp;
ql_dbg(ql_dbg_tgt, ha, 0xe008, ql_dbg(ql_dbg_tgt, ha, 0xe008,
"Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n", "Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n",
@ -1292,7 +1293,8 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
ctio->u.status1.flags = (atio->u.isp24.attr << 9) | ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 |
CTIO7_FLAGS_SEND_STATUS); CTIO7_FLAGS_SEND_STATUS);
ctio->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio->u.status1.ox_id = cpu_to_le16(temp);
ctio->u.status1.scsi_status = ctio->u.status1.scsi_status =
__constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
ctio->u.status1.response_len = __constant_cpu_to_le16(8); ctio->u.status1.response_len = __constant_cpu_to_le16(8);
@ -1513,6 +1515,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
struct ctio7_to_24xx *pkt; struct ctio7_to_24xx *pkt;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct atio_from_isp *atio = &prm->cmd->atio; struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t temp;
pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr; pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr;
prm->pkt = pkt; prm->pkt = pkt;
@ -1541,13 +1544,13 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
pkt->exchange_addr = atio->u.isp24.exchange_addr; pkt->exchange_addr = atio->u.isp24.exchange_addr;
pkt->u.status0.flags |= (atio->u.isp24.attr << 9); pkt->u.status0.flags |= (atio->u.isp24.attr << 9);
pkt->u.status0.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
pkt->u.status0.ox_id = cpu_to_le16(temp);
pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset); pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset);
ql_dbg(ql_dbg_tgt, vha, 0xe00c, ql_dbg(ql_dbg_tgt, vha, 0xe00c,
"qla_target(%d): handle(cmd) -> %08x, timeout %d, ox_id %#x\n", "qla_target(%d): handle(cmd) -> %08x, timeout %d, ox_id %#x\n",
vha->vp_idx, pkt->handle, QLA_TGT_TIMEOUT, vha->vp_idx, pkt->handle, QLA_TGT_TIMEOUT, temp);
le16_to_cpu(pkt->u.status0.ox_id));
return 0; return 0;
} }
@ -2619,6 +2622,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
request_t *pkt; request_t *pkt;
int ret = 0; int ret = 0;
uint16_t temp;
ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha); ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha);
@ -2655,7 +2659,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | ctio24->u.status1.flags = (atio->u.isp24.attr << 9) |
__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 |
CTIO7_FLAGS_TERMINATE); CTIO7_FLAGS_TERMINATE);
ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio24->u.status1.ox_id = cpu_to_le16(temp);
/* Most likely, it isn't needed */ /* Most likely, it isn't needed */
ctio24->u.status1.residual = get_unaligned((uint32_t *) ctio24->u.status1.residual = get_unaligned((uint32_t *)

View File

@ -443,7 +443,7 @@ struct ctio7_to_24xx {
uint16_t reserved1; uint16_t reserved1;
__le16 flags; __le16 flags;
uint32_t residual; uint32_t residual;
uint16_t ox_id; __le16 ox_id;
uint16_t scsi_status; uint16_t scsi_status;
uint32_t relative_offset; uint32_t relative_offset;
uint32_t reserved2; uint32_t reserved2;
@ -458,7 +458,7 @@ struct ctio7_to_24xx {
uint16_t sense_length; uint16_t sense_length;
uint16_t flags; uint16_t flags;
uint32_t residual; uint32_t residual;
uint16_t ox_id; __le16 ox_id;
uint16_t scsi_status; uint16_t scsi_status;
uint16_t response_len; uint16_t response_len;
uint16_t reserved; uint16_t reserved;

View File

@ -131,7 +131,7 @@ scmd_eh_abort_handler(struct work_struct *work)
"aborting command %p\n", scmd)); "aborting command %p\n", scmd));
rtn = scsi_try_to_abort_cmd(sdev->host->hostt, scmd); rtn = scsi_try_to_abort_cmd(sdev->host->hostt, scmd);
if (rtn == SUCCESS) { if (rtn == SUCCESS) {
scmd->result |= DID_TIME_OUT << 16; set_host_byte(scmd, DID_TIME_OUT);
if (scsi_host_eh_past_deadline(sdev->host)) { if (scsi_host_eh_past_deadline(sdev->host)) {
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd, scmd_printk(KERN_INFO, scmd,
@ -167,7 +167,7 @@ scmd_eh_abort_handler(struct work_struct *work)
scmd_printk(KERN_WARNING, scmd, scmd_printk(KERN_WARNING, scmd,
"scmd %p terminate " "scmd %p terminate "
"aborted command\n", scmd)); "aborted command\n", scmd));
scmd->result |= DID_TIME_OUT << 16; set_host_byte(scmd, DID_TIME_OUT);
scsi_finish_command(scmd); scsi_finish_command(scmd);
} }
} }
@ -287,15 +287,15 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
else if (host->hostt->eh_timed_out) else if (host->hostt->eh_timed_out)
rtn = host->hostt->eh_timed_out(scmd); rtn = host->hostt->eh_timed_out(scmd);
if (rtn == BLK_EH_NOT_HANDLED && !host->hostt->no_async_abort) if (rtn == BLK_EH_NOT_HANDLED) {
if (scsi_abort_command(scmd) == SUCCESS) if (!host->hostt->no_async_abort &&
scsi_abort_command(scmd) == SUCCESS)
return BLK_EH_NOT_HANDLED; return BLK_EH_NOT_HANDLED;
scmd->result |= DID_TIME_OUT << 16; set_host_byte(scmd, DID_TIME_OUT);
if (!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))
if (unlikely(rtn == BLK_EH_NOT_HANDLED && rtn = BLK_EH_HANDLED;
!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) }
rtn = BLK_EH_HANDLED;
return rtn; return rtn;
} }
@ -1777,7 +1777,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
break; break;
case DID_ABORT: case DID_ABORT:
if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) { if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
scmd->result |= DID_TIME_OUT << 16; set_host_byte(scmd, DID_TIME_OUT);
return SUCCESS; return SUCCESS;
} }
case DID_NO_CONNECT: case DID_NO_CONNECT:

View File

@ -2549,6 +2549,7 @@ fc_rport_final_delete(struct work_struct *work)
fc_flush_devloss(shost); fc_flush_devloss(shost);
if (!cancel_delayed_work(&rport->dev_loss_work)) if (!cancel_delayed_work(&rport->dev_loss_work))
fc_flush_devloss(shost); fc_flush_devloss(shost);
cancel_work_sync(&rport->scan_work);
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
} }

View File

@ -237,6 +237,16 @@ static void virtscsi_req_done(struct virtqueue *vq)
virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd);
}; };
static void virtscsi_poll_requests(struct virtio_scsi *vscsi)
{
int i, num_vqs;
num_vqs = vscsi->num_queues;
for (i = 0; i < num_vqs; i++)
virtscsi_vq_done(vscsi, &vscsi->req_vqs[i],
virtscsi_complete_cmd);
}
static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf)
{ {
struct virtio_scsi_cmd *cmd = buf; struct virtio_scsi_cmd *cmd = buf;
@ -253,6 +263,8 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free); virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free);
}; };
static void virtscsi_handle_event(struct work_struct *work);
static int virtscsi_kick_event(struct virtio_scsi *vscsi, static int virtscsi_kick_event(struct virtio_scsi *vscsi,
struct virtio_scsi_event_node *event_node) struct virtio_scsi_event_node *event_node)
{ {
@ -260,6 +272,7 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
struct scatterlist sg; struct scatterlist sg;
unsigned long flags; unsigned long flags;
INIT_WORK(&event_node->work, virtscsi_handle_event);
sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
@ -377,7 +390,6 @@ static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf)
{ {
struct virtio_scsi_event_node *event_node = buf; struct virtio_scsi_event_node *event_node = buf;
INIT_WORK(&event_node->work, virtscsi_handle_event);
schedule_work(&event_node->work); schedule_work(&event_node->work);
} }
@ -589,6 +601,18 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED)
ret = SUCCESS; ret = SUCCESS;
/*
* The spec guarantees that all requests related to the TMF have
* been completed, but the callback might not have run yet if
* we're using independent interrupts (e.g. MSI). Poll the
* virtqueues once.
*
* In the abort case, sc->scsi_done will do nothing, because
* the block layer must have detected a timeout and as a result
* REQ_ATOM_COMPLETE has been set.
*/
virtscsi_poll_requests(vscsi);
out: out:
mempool_free(cmd, virtscsi_cmd_pool); mempool_free(cmd, virtscsi_cmd_pool);
return ret; return ret;

View File

@ -318,7 +318,7 @@ static inline void set_driver_byte(struct scsi_cmnd *cmd, char status)
static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd) static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd)
{ {
unsigned int xfer_len = blk_rq_bytes(scmd->request); unsigned int xfer_len = scsi_out(scmd)->length;
unsigned int prot_op = scsi_get_prot_op(scmd); unsigned int prot_op = scsi_get_prot_op(scmd);
unsigned int sector_size = scmd->device->sector_size; unsigned int sector_size = scmd->device->sector_size;