Commit 5f8ebd36 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull SCSI fixes from James Bottomley:
 "This is a set of three fixes for data corruption (libsas task file),
  oops causing (NULL in scsi_cmd_to_driver) and driver failure (bnx2i).
  The oops caused by the NULL in scsi_cmd_to_driver() manifests in
  scsi_eh_send_cmd() and has been seen by several people now.

  Signed-off-by: James Bottomley <JBottomley@Parallels.com>"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  [SCSI] bnx2i: Removed the reference to the netdev->base_addr
  [SCSI] libsas: fix taskfile corruption in sas_ata_qc_fill_rtf
  [SCSI] Fix NULL dereferences in scsi_cmd_to_driver
parents 8a76e538 a7717180
...@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb, ...@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
resp->frame_len = le16_to_cpu(*(__le16 *)(r+6)); resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
memcpy(&resp->ending_fis[0], r+16, 24); memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
ts->buf_valid_size = sizeof(*resp); ts->buf_valid_size = sizeof(*resp);
} }
} }
......
...@@ -350,6 +350,7 @@ struct bnx2i_hba { ...@@ -350,6 +350,7 @@ struct bnx2i_hba {
struct pci_dev *pcidev; struct pci_dev *pcidev;
struct net_device *netdev; struct net_device *netdev;
void __iomem *regview; void __iomem *regview;
resource_size_t reg_base;
u32 age; u32 age;
unsigned long cnic_dev_type; unsigned long cnic_dev_type;
......
...@@ -2724,7 +2724,6 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) ...@@ -2724,7 +2724,6 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
goto arm_cq; goto arm_cq;
} }
reg_base = ep->hba->netdev->base_addr;
if ((test_bit(BNX2I_NX2_DEV_5709, &ep->hba->cnic_dev_type)) && if ((test_bit(BNX2I_NX2_DEV_5709, &ep->hba->cnic_dev_type)) &&
(ep->hba->mail_queue_access == BNX2I_MQ_BIN_MODE)) { (ep->hba->mail_queue_access == BNX2I_MQ_BIN_MODE)) {
config2 = REG_RD(ep->hba, BNX2_MQ_CONFIG2); config2 = REG_RD(ep->hba, BNX2_MQ_CONFIG2);
...@@ -2740,7 +2739,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) ...@@ -2740,7 +2739,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
/* 5709 device in normal node and 5706/5708 devices */ /* 5709 device in normal node and 5706/5708 devices */
reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num); reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num);
ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, ep->qp.ctx_base = ioremap_nocache(ep->hba->reg_base + reg_off,
MB_KERNEL_CTX_SIZE); MB_KERNEL_CTX_SIZE);
if (!ep->qp.ctx_base) if (!ep->qp.ctx_base)
return -ENOMEM; return -ENOMEM;
......
...@@ -811,13 +811,13 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) ...@@ -811,13 +811,13 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
bnx2i_identify_device(hba); bnx2i_identify_device(hba);
bnx2i_setup_host_queue_size(hba, shost); bnx2i_setup_host_queue_size(hba, shost);
hba->reg_base = pci_resource_start(hba->pcidev, 0);
if (test_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type)) { if (test_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type)) {
hba->regview = ioremap_nocache(hba->netdev->base_addr, hba->regview = pci_iomap(hba->pcidev, 0, BNX2_MQ_CONFIG2);
BNX2_MQ_CONFIG2);
if (!hba->regview) if (!hba->regview)
goto ioreg_map_err; goto ioreg_map_err;
} else if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { } else if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
hba->regview = ioremap_nocache(hba->netdev->base_addr, 4096); hba->regview = pci_iomap(hba->pcidev, 0, 4096);
if (!hba->regview) if (!hba->regview)
goto ioreg_map_err; goto ioreg_map_err;
} }
...@@ -884,7 +884,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) ...@@ -884,7 +884,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
bnx2i_free_mp_bdt(hba); bnx2i_free_mp_bdt(hba);
mp_bdt_mem_err: mp_bdt_mem_err:
if (hba->regview) { if (hba->regview) {
iounmap(hba->regview); pci_iounmap(hba->pcidev, hba->regview);
hba->regview = NULL; hba->regview = NULL;
} }
ioreg_map_err: ioreg_map_err:
...@@ -910,7 +910,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba) ...@@ -910,7 +910,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba)
pci_dev_put(hba->pcidev); pci_dev_put(hba->pcidev);
if (hba->regview) { if (hba->regview) {
iounmap(hba->regview); pci_iounmap(hba->pcidev, hba->regview);
hba->regview = NULL; hba->regview = NULL;
} }
bnx2i_free_mp_bdt(hba); bnx2i_free_mp_bdt(hba);
......
...@@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas_task *task) ...@@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas_task *task)
if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
((stat->stat == SAM_STAT_CHECK_CONDITION && ((stat->stat == SAM_STAT_CHECK_CONDITION &&
dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);
if (!link->sactive) { if (!link->sactive) {
qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
} else { } else {
link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
if (unlikely(link->eh_info.err_mask)) if (unlikely(link->eh_info.err_mask))
qc->flags |= ATA_QCFLAG_FAILED; qc->flags |= ATA_QCFLAG_FAILED;
} }
...@@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task) ...@@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task)
qc->flags |= ATA_QCFLAG_FAILED; qc->flags |= ATA_QCFLAG_FAILED;
} }
dev->sata_dev.tf.feature = 0x04; /* status err */ dev->sata_dev.fis[3] = 0x04; /* status err */
dev->sata_dev.tf.command = ATA_ERR; dev->sata_dev.fis[2] = ATA_ERR;
} }
} }
...@@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) ...@@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
{ {
struct domain_device *dev = qc->ap->private_data; struct domain_device *dev = qc->ap->private_data;
memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf)); ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
return true; return true;
} }
......
...@@ -163,6 +163,8 @@ enum ata_command_set { ...@@ -163,6 +163,8 @@ enum ata_command_set {
ATAPI_COMMAND_SET = 1, ATAPI_COMMAND_SET = 1,
}; };
#define ATA_RESP_FIS_SIZE 24
struct sata_device { struct sata_device {
enum ata_command_set command_set; enum ata_command_set command_set;
struct smp_resp rps_resp; /* report_phy_sata_resp */ struct smp_resp rps_resp; /* report_phy_sata_resp */
...@@ -171,7 +173,7 @@ struct sata_device { ...@@ -171,7 +173,7 @@ struct sata_device {
struct ata_port *ap; struct ata_port *ap;
struct ata_host ata_host; struct ata_host ata_host;
struct ata_taskfile tf; u8 fis[ATA_RESP_FIS_SIZE];
}; };
enum { enum {
...@@ -537,7 +539,7 @@ enum exec_status { ...@@ -537,7 +539,7 @@ enum exec_status {
*/ */
struct ata_task_resp { struct ata_task_resp {
u16 frame_len; u16 frame_len;
u8 ending_fis[24]; /* dev to host or data-in */ u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */
}; };
#define SAS_STATUS_BUF_SIZE 96 #define SAS_STATUS_BUF_SIZE 96
......
...@@ -134,10 +134,16 @@ struct scsi_cmnd { ...@@ -134,10 +134,16 @@ struct scsi_cmnd {
static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
{ {
struct scsi_driver **sdp;
if (!cmd->request->rq_disk) if (!cmd->request->rq_disk)
return NULL; return NULL;
return *(struct scsi_driver **)cmd->request->rq_disk->private_data; sdp = (struct scsi_driver **)cmd->request->rq_disk->private_data;
if (!sdp)
return NULL;
return *sdp;
} }
extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment