Commit 0aa3fdb8 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 four patches, consisting of one regression from the merge
  window (qla2xxx), one long-standing memory leak (sd_zbc), one event
  queue mislabelling which we want to eliminate to discourage the
  pattern (mpt3sas), and one behaviour change because re-reading the
  partition table shouldn't clear the ro flag"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: sd: Keep disk read-only when re-reading partition
  scsi: qla2xxx: Fix crashes in qla2x00_probe_one on probe failure
  scsi: sd_zbc: Fix potential memory leak
  scsi: mpt3sas: Do not mark fw_event workqueue as WQ_MEM_RECLAIM
parents 8df3aaaf 20bd1d02
...@@ -10558,7 +10558,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -10558,7 +10558,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
"fw_event_%s%d", ioc->driver_name, ioc->id); "fw_event_%s%d", ioc->driver_name, ioc->id);
ioc->firmware_event_thread = alloc_ordered_workqueue( ioc->firmware_event_thread = alloc_ordered_workqueue(
ioc->firmware_event_name, WQ_MEM_RECLAIM); ioc->firmware_event_name, 0);
if (!ioc->firmware_event_thread) { if (!ioc->firmware_event_thread) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__); ioc->name, __FILE__, __LINE__, __func__);
......
...@@ -454,7 +454,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, ...@@ -454,7 +454,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
ha->req_q_map[0] = req; ha->req_q_map[0] = req;
set_bit(0, ha->rsp_qid_map); set_bit(0, ha->rsp_qid_map);
set_bit(0, ha->req_qid_map); set_bit(0, ha->req_qid_map);
return 1; return 0;
fail_qpair_map: fail_qpair_map:
kfree(ha->base_qpair); kfree(ha->base_qpair);
...@@ -471,6 +471,9 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, ...@@ -471,6 +471,9 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
{ {
if (!ha->req_q_map)
return;
if (IS_QLAFX00(ha)) { if (IS_QLAFX00(ha)) {
if (req && req->ring_fx00) if (req && req->ring_fx00)
dma_free_coherent(&ha->pdev->dev, dma_free_coherent(&ha->pdev->dev,
...@@ -481,14 +484,17 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) ...@@ -481,14 +484,17 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
(req->length + 1) * sizeof(request_t), (req->length + 1) * sizeof(request_t),
req->ring, req->dma); req->ring, req->dma);
if (req) if (req) {
kfree(req->outstanding_cmds); kfree(req->outstanding_cmds);
kfree(req);
kfree(req); }
} }
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp) static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
{ {
if (!ha->rsp_q_map)
return;
if (IS_QLAFX00(ha)) { if (IS_QLAFX00(ha)) {
if (rsp && rsp->ring) if (rsp && rsp->ring)
dma_free_coherent(&ha->pdev->dev, dma_free_coherent(&ha->pdev->dev,
...@@ -499,7 +505,8 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp) ...@@ -499,7 +505,8 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
(rsp->length + 1) * sizeof(response_t), (rsp->length + 1) * sizeof(response_t),
rsp->ring, rsp->dma); rsp->ring, rsp->dma);
} }
kfree(rsp); if (rsp)
kfree(rsp);
} }
static void qla2x00_free_queues(struct qla_hw_data *ha) static void qla2x00_free_queues(struct qla_hw_data *ha)
...@@ -1723,6 +1730,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) ...@@ -1723,6 +1730,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
struct qla_tgt_cmd *cmd; struct qla_tgt_cmd *cmd;
uint8_t trace = 0; uint8_t trace = 0;
if (!ha->req_q_map)
return;
spin_lock_irqsave(qp->qp_lock_ptr, flags); spin_lock_irqsave(qp->qp_lock_ptr, flags);
req = qp->req; req = qp->req;
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
...@@ -3095,14 +3104,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -3095,14 +3104,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set up the irqs */ /* Set up the irqs */
ret = qla2x00_request_irqs(ha, rsp); ret = qla2x00_request_irqs(ha, rsp);
if (ret) if (ret)
goto probe_hw_failed; goto probe_failed;
/* Alloc arrays of request and response ring ptrs */ /* Alloc arrays of request and response ring ptrs */
if (!qla2x00_alloc_queues(ha, req, rsp)) { if (qla2x00_alloc_queues(ha, req, rsp)) {
ql_log(ql_log_fatal, base_vha, 0x003d, ql_log(ql_log_fatal, base_vha, 0x003d,
"Failed to allocate memory for queue pointers..." "Failed to allocate memory for queue pointers..."
"aborting.\n"); "aborting.\n");
goto probe_init_failed; goto probe_failed;
} }
if (ha->mqenable && shost_use_blk_mq(host)) { if (ha->mqenable && shost_use_blk_mq(host)) {
...@@ -3387,15 +3396,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -3387,15 +3396,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return 0; return 0;
probe_init_failed:
qla2x00_free_req_que(ha, req);
ha->req_q_map[0] = NULL;
clear_bit(0, ha->req_qid_map);
qla2x00_free_rsp_que(ha, rsp);
ha->rsp_q_map[0] = NULL;
clear_bit(0, ha->rsp_qid_map);
ha->max_req_queues = ha->max_rsp_queues = 0;
probe_failed: probe_failed:
if (base_vha->timer_active) if (base_vha->timer_active)
qla2x00_stop_timer(base_vha); qla2x00_stop_timer(base_vha);
...@@ -4508,11 +4508,17 @@ qla2x00_mem_free(struct qla_hw_data *ha) ...@@ -4508,11 +4508,17 @@ qla2x00_mem_free(struct qla_hw_data *ha)
if (ha->init_cb) if (ha->init_cb)
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
ha->init_cb, ha->init_cb_dma); ha->init_cb, ha->init_cb_dma);
vfree(ha->optrom_buffer);
kfree(ha->nvram); if (ha->optrom_buffer)
kfree(ha->npiv_info); vfree(ha->optrom_buffer);
kfree(ha->swl); if (ha->nvram)
kfree(ha->loop_id_map); kfree(ha->nvram);
if (ha->npiv_info)
kfree(ha->npiv_info);
if (ha->swl)
kfree(ha->swl);
if (ha->loop_id_map)
kfree(ha->loop_id_map);
ha->srb_mempool = NULL; ha->srb_mempool = NULL;
ha->ctx_mempool = NULL; ha->ctx_mempool = NULL;
...@@ -4528,6 +4534,15 @@ qla2x00_mem_free(struct qla_hw_data *ha) ...@@ -4528,6 +4534,15 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->ex_init_cb_dma = 0; ha->ex_init_cb_dma = 0;
ha->async_pd = NULL; ha->async_pd = NULL;
ha->async_pd_dma = 0; ha->async_pd_dma = 0;
ha->loop_id_map = NULL;
ha->npiv_info = NULL;
ha->optrom_buffer = NULL;
ha->swl = NULL;
ha->nvram = NULL;
ha->mctp_dump = NULL;
ha->dcbx_tlv = NULL;
ha->xgmac_data = NULL;
ha->sfp_data = NULL;
ha->s_dma_pool = NULL; ha->s_dma_pool = NULL;
ha->dl_dma_pool = NULL; ha->dl_dma_pool = NULL;
......
...@@ -2595,6 +2595,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) ...@@ -2595,6 +2595,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
int res; int res;
struct scsi_device *sdp = sdkp->device; struct scsi_device *sdp = sdkp->device;
struct scsi_mode_data data; struct scsi_mode_data data;
int disk_ro = get_disk_ro(sdkp->disk);
int old_wp = sdkp->write_prot; int old_wp = sdkp->write_prot;
set_disk_ro(sdkp->disk, 0); set_disk_ro(sdkp->disk, 0);
...@@ -2635,7 +2636,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) ...@@ -2635,7 +2636,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
"Test WP failed, assume Write Enabled\n"); "Test WP failed, assume Write Enabled\n");
} else { } else {
sdkp->write_prot = ((data.device_specific & 0x80) != 0); sdkp->write_prot = ((data.device_specific & 0x80) != 0);
set_disk_ro(sdkp->disk, sdkp->write_prot); set_disk_ro(sdkp->disk, sdkp->write_prot || disk_ro);
if (sdkp->first_scan || old_wp != sdkp->write_prot) { if (sdkp->first_scan || old_wp != sdkp->write_prot) {
sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
sdkp->write_prot ? "on" : "off"); sdkp->write_prot ? "on" : "off");
......
...@@ -403,7 +403,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf) ...@@ -403,7 +403,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf)
*/ */
static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
{ {
u64 zone_blocks; u64 zone_blocks = 0;
sector_t block = 0; sector_t block = 0;
unsigned char *buf; unsigned char *buf;
unsigned char *rec; unsigned char *rec;
...@@ -421,10 +421,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -421,10 +421,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
/* Do a report zone to get the same field */ /* Do a report zone to get the same field */
ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0); ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0);
if (ret) { if (ret)
zone_blocks = 0; goto out_free;
goto out;
}
same = buf[4] & 0x0f; same = buf[4] & 0x0f;
if (same > 0) { if (same > 0) {
...@@ -464,7 +462,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -464,7 +462,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
ret = sd_zbc_report_zones(sdkp, buf, ret = sd_zbc_report_zones(sdkp, buf,
SD_ZBC_BUF_SIZE, block); SD_ZBC_BUF_SIZE, block);
if (ret) if (ret)
return ret; goto out_free;
} }
} while (block < sdkp->capacity); } while (block < sdkp->capacity);
...@@ -472,35 +470,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -472,35 +470,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
zone_blocks = sdkp->zone_blocks; zone_blocks = sdkp->zone_blocks;
out: out:
kfree(buf);
if (!zone_blocks) { if (!zone_blocks) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Devices with non constant zone " "Devices with non constant zone "
"size are not supported\n"); "size are not supported\n");
return -ENODEV; ret = -ENODEV;
} } else if (!is_power_of_2(zone_blocks)) {
if (!is_power_of_2(zone_blocks)) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Devices with non power of 2 zone " "Devices with non power of 2 zone "
"size are not supported\n"); "size are not supported\n");
return -ENODEV; ret = -ENODEV;
} } else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Zone size too large\n"); "Zone size too large\n");
return -ENODEV; ret = -ENODEV;
} else {
sdkp->zone_blocks = zone_blocks;
sdkp->zone_shift = ilog2(zone_blocks);
} }
sdkp->zone_blocks = zone_blocks; out_free:
sdkp->zone_shift = ilog2(zone_blocks); kfree(buf);
return 0; return ret;
} }
/** /**
......
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