Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0aa3fdb8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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),
	    "fw_event_%s%d", ioc->driver_name, ioc->id);
	ioc->firmware_event_thread = alloc_ordered_workqueue(
	    ioc->firmware_event_name, WQ_MEM_RECLAIM);
	    ioc->firmware_event_name, 0);
	if (!ioc->firmware_event_thread) {
		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
		    ioc->name, __FILE__, __LINE__, __func__);
+37 −22
Original line number Diff line number Diff line
@@ -454,7 +454,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
	ha->req_q_map[0] = req;
	set_bit(0, ha->rsp_qid_map);
	set_bit(0, ha->req_qid_map);
	return 1;
	return 0;

fail_qpair_map:
	kfree(ha->base_qpair);
@@ -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)
{
	if (!ha->req_q_map)
		return;

	if (IS_QLAFX00(ha)) {
		if (req && req->ring_fx00)
			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)
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	if (req)
	if (req) {
		kfree(req->outstanding_cmds);

		kfree(req);
	}
}

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 (rsp && rsp->ring)
			dma_free_coherent(&ha->pdev->dev,
@@ -499,6 +505,7 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
		(rsp->length + 1) * sizeof(response_t),
		rsp->ring, rsp->dma);
	}
	if (rsp)
		kfree(rsp);
}

@@ -1723,6 +1730,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
	struct qla_tgt_cmd *cmd;
	uint8_t trace = 0;

	if (!ha->req_q_map)
		return;
	spin_lock_irqsave(qp->qp_lock_ptr, flags);
	req = qp->req;
	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)
	/* Set up the irqs */
	ret = qla2x00_request_irqs(ha, rsp);
	if (ret)
		goto probe_hw_failed;
		goto probe_failed;

	/* 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,
		    "Failed to allocate memory for queue pointers..."
		    "aborting.\n");
		goto probe_init_failed;
		goto probe_failed;
	}

	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)

	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:
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);
@@ -4508,10 +4508,16 @@ qla2x00_mem_free(struct qla_hw_data *ha)
	if (ha->init_cb)
		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
			ha->init_cb, ha->init_cb_dma);

	if (ha->optrom_buffer)
		vfree(ha->optrom_buffer);
	if (ha->nvram)
		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;
@@ -4528,6 +4534,15 @@ qla2x00_mem_free(struct qla_hw_data *ha)
	ha->ex_init_cb_dma = 0;
	ha->async_pd = NULL;
	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->dl_dma_pool = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -2595,6 +2595,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
	int res;
	struct scsi_device *sdp = sdkp->device;
	struct scsi_mode_data data;
	int disk_ro = get_disk_ro(sdkp->disk);
	int old_wp = sdkp->write_prot;

	set_disk_ro(sdkp->disk, 0);
@@ -2635,7 +2636,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
			  "Test WP failed, assume Write Enabled\n");
	} else {
		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) {
			sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
				  sdkp->write_prot ? "on" : "off");
+15 −20
Original line number Diff line number Diff line
@@ -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)
{
	u64 zone_blocks;
	u64 zone_blocks = 0;
	sector_t block = 0;
	unsigned char *buf;
	unsigned char *rec;
@@ -421,10 +421,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)

	/* Do a report zone to get the same field */
	ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0);
	if (ret) {
		zone_blocks = 0;
		goto out;
	}
	if (ret)
		goto out_free;

	same = buf[4] & 0x0f;
	if (same > 0) {
@@ -464,7 +462,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
			ret = sd_zbc_report_zones(sdkp, buf,
						  SD_ZBC_BUF_SIZE, block);
			if (ret)
				return ret;
				goto out_free;
		}

	} while (block < sdkp->capacity);
@@ -472,35 +470,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
	zone_blocks = sdkp->zone_blocks;

out:
	kfree(buf);

	if (!zone_blocks) {
		if (sdkp->first_scan)
			sd_printk(KERN_NOTICE, sdkp,
				  "Devices with non constant zone "
				  "size are not supported\n");
		return -ENODEV;
	}

	if (!is_power_of_2(zone_blocks)) {
		ret = -ENODEV;
	} else if (!is_power_of_2(zone_blocks)) {
		if (sdkp->first_scan)
			sd_printk(KERN_NOTICE, sdkp,
				  "Devices with non power of 2 zone "
				  "size are not supported\n");
		return -ENODEV;
	}

	if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
		ret = -ENODEV;
	} else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
		if (sdkp->first_scan)
			sd_printk(KERN_NOTICE, sdkp,
				  "Zone size too large\n");
		return -ENODEV;
	}

		ret = -ENODEV;
	} else {
		sdkp->zone_blocks = zone_blocks;
		sdkp->zone_shift = ilog2(zone_blocks);
	}

	return 0;
out_free:
	kfree(buf);

	return ret;
}

/**