Commit cf76c364 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:
 "Four obvious bug fixes. The vmw_pscsi is so old that it's amazing
  no-one noticed before now"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: storvsc: Fix a race in sub-channel creation that can cause panic
  scsi: vmw_pscsi: Rearrange code to avoid multiple calls to free_irq during unload
  scsi: libiscsi: Fix NULL pointer dereference in iscsi_eh_session_reset
  scsi: lpfc: fix block guard enablement on SLI3 adapters
parents 369af92c c9675904
...@@ -2416,8 +2416,8 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc) ...@@ -2416,8 +2416,8 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc)
failed: failed:
ISCSI_DBG_EH(session, ISCSI_DBG_EH(session,
"failing session reset: Could not log back into " "failing session reset: Could not log back into "
"%s, %s [age %d]\n", session->targetname, "%s [age %d]\n", session->targetname,
conn->persistent_address, session->age); session->age);
spin_unlock_bh(&session->frwd_lock); spin_unlock_bh(&session->frwd_lock);
mutex_unlock(&session->eh_mutex); mutex_unlock(&session->eh_mutex);
return FAILED; return FAILED;
......
...@@ -167,7 +167,11 @@ lpfc_config_port_prep(struct lpfc_hba *phba) ...@@ -167,7 +167,11 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
sizeof(phba->wwpn)); sizeof(phba->wwpn));
} }
phba->sli3_options = 0x0; /*
* Clear all option bits except LPFC_SLI3_BG_ENABLED,
* which was already set in lpfc_get_cfgparam()
*/
phba->sli3_options &= (uint32_t)LPFC_SLI3_BG_ENABLED;
/* Setup and issue mailbox READ REV command */ /* Setup and issue mailbox READ REV command */
lpfc_read_rev(phba, pmb); lpfc_read_rev(phba, pmb);
......
...@@ -4965,7 +4965,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) ...@@ -4965,7 +4965,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |
LPFC_SLI3_HBQ_ENABLED | LPFC_SLI3_HBQ_ENABLED |
LPFC_SLI3_CRP_ENABLED | LPFC_SLI3_CRP_ENABLED |
LPFC_SLI3_BG_ENABLED |
LPFC_SLI3_DSS_ENABLED); LPFC_SLI3_DSS_ENABLED);
if (rc != MBX_SUCCESS) { if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
......
...@@ -446,7 +446,6 @@ struct storvsc_device { ...@@ -446,7 +446,6 @@ struct storvsc_device {
bool destroy; bool destroy;
bool drain_notify; bool drain_notify;
bool open_sub_channel;
atomic_t num_outstanding_req; atomic_t num_outstanding_req;
struct Scsi_Host *host; struct Scsi_Host *host;
...@@ -636,33 +635,38 @@ static inline struct storvsc_device *get_in_stor_device( ...@@ -636,33 +635,38 @@ static inline struct storvsc_device *get_in_stor_device(
static void handle_sc_creation(struct vmbus_channel *new_sc) static void handle_sc_creation(struct vmbus_channel *new_sc)
{ {
struct hv_device *device = new_sc->primary_channel->device_obj; struct hv_device *device = new_sc->primary_channel->device_obj;
struct device *dev = &device->device;
struct storvsc_device *stor_device; struct storvsc_device *stor_device;
struct vmstorage_channel_properties props; struct vmstorage_channel_properties props;
int ret;
stor_device = get_out_stor_device(device); stor_device = get_out_stor_device(device);
if (!stor_device) if (!stor_device)
return; return;
if (stor_device->open_sub_channel == false)
return;
memset(&props, 0, sizeof(struct vmstorage_channel_properties)); memset(&props, 0, sizeof(struct vmstorage_channel_properties));
vmbus_open(new_sc, ret = vmbus_open(new_sc,
storvsc_ringbuffer_size, storvsc_ringbuffer_size,
storvsc_ringbuffer_size, storvsc_ringbuffer_size,
(void *)&props, (void *)&props,
sizeof(struct vmstorage_channel_properties), sizeof(struct vmstorage_channel_properties),
storvsc_on_channel_callback, new_sc); storvsc_on_channel_callback, new_sc);
if (new_sc->state == CHANNEL_OPENED_STATE) { /* In case vmbus_open() fails, we don't use the sub-channel. */
stor_device->stor_chns[new_sc->target_cpu] = new_sc; if (ret != 0) {
cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); dev_err(dev, "Failed to open sub-channel: err=%d\n", ret);
return;
} }
/* Add the sub-channel to the array of available channels. */
stor_device->stor_chns[new_sc->target_cpu] = new_sc;
cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus);
} }
static void handle_multichannel_storage(struct hv_device *device, int max_chns) static void handle_multichannel_storage(struct hv_device *device, int max_chns)
{ {
struct device *dev = &device->device;
struct storvsc_device *stor_device; struct storvsc_device *stor_device;
int num_cpus = num_online_cpus(); int num_cpus = num_online_cpus();
int num_sc; int num_sc;
...@@ -679,21 +683,11 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) ...@@ -679,21 +683,11 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns)
request = &stor_device->init_request; request = &stor_device->init_request;
vstor_packet = &request->vstor_packet; vstor_packet = &request->vstor_packet;
stor_device->open_sub_channel = true;
/* /*
* Establish a handler for dealing with subchannels. * Establish a handler for dealing with subchannels.
*/ */
vmbus_set_sc_create_callback(device->channel, handle_sc_creation); vmbus_set_sc_create_callback(device->channel, handle_sc_creation);
/*
* Check to see if sub-channels have already been created. This
* can happen when this driver is re-loaded after unloading.
*/
if (vmbus_are_subchannels_present(device->channel))
return;
stor_device->open_sub_channel = false;
/* /*
* Request the host to create sub-channels. * Request the host to create sub-channels.
*/ */
...@@ -710,23 +704,29 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) ...@@ -710,23 +704,29 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns)
VM_PKT_DATA_INBAND, VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0) if (ret != 0) {
dev_err(dev, "Failed to create sub-channel: err=%d\n", ret);
return; return;
}
t = wait_for_completion_timeout(&request->wait_event, 10*HZ); t = wait_for_completion_timeout(&request->wait_event, 10*HZ);
if (t == 0) if (t == 0) {
dev_err(dev, "Failed to create sub-channel: timed out\n");
return; return;
}
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
vstor_packet->status != 0) vstor_packet->status != 0) {
dev_err(dev, "Failed to create sub-channel: op=%d, sts=%d\n",
vstor_packet->operation, vstor_packet->status);
return; return;
}
/* /*
* Now that we created the sub-channels, invoke the check; this * We need to do nothing here, because vmbus_process_offer()
* may trigger the callback. * invokes channel->sc_creation_callback, which will open and use
* the sub-channel(s).
*/ */
stor_device->open_sub_channel = true;
vmbus_are_subchannels_present(device->channel);
} }
static void cache_wwn(struct storvsc_device *stor_device, static void cache_wwn(struct storvsc_device *stor_device,
...@@ -1794,7 +1794,6 @@ static int storvsc_probe(struct hv_device *device, ...@@ -1794,7 +1794,6 @@ static int storvsc_probe(struct hv_device *device,
} }
stor_device->destroy = false; stor_device->destroy = false;
stor_device->open_sub_channel = false;
init_waitqueue_head(&stor_device->waiting_to_drain); init_waitqueue_head(&stor_device->waiting_to_drain);
stor_device->device = device; stor_device->device = device;
stor_device->host = host; stor_device->host = host;
......
...@@ -1202,8 +1202,6 @@ static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter) ...@@ -1202,8 +1202,6 @@ static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
static void pvscsi_release_resources(struct pvscsi_adapter *adapter) static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
{ {
pvscsi_shutdown_intr(adapter);
if (adapter->workqueue) if (adapter->workqueue)
destroy_workqueue(adapter->workqueue); destroy_workqueue(adapter->workqueue);
...@@ -1534,6 +1532,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1534,6 +1532,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_reset_adapter: out_reset_adapter:
ll_adapter_reset(adapter); ll_adapter_reset(adapter);
out_release_resources: out_release_resources:
pvscsi_shutdown_intr(adapter);
pvscsi_release_resources(adapter); pvscsi_release_resources(adapter);
scsi_host_put(host); scsi_host_put(host);
out_disable_device: out_disable_device:
...@@ -1542,6 +1541,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1542,6 +1541,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return error; return error;
out_release_resources_and_disable: out_release_resources_and_disable:
pvscsi_shutdown_intr(adapter);
pvscsi_release_resources(adapter); pvscsi_release_resources(adapter);
goto out_disable_device; goto out_disable_device;
} }
......
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