From f64dad2628bdf62eac7ac145a6e31430376b65e4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 14 Dec 2016 18:45:58 -0800 Subject: scsi: storvsc: Enable tracking of queue depth Enable tracking of queue depth. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 05526b71541b..ccb2101c6385 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1550,6 +1550,7 @@ static struct scsi_host_template scsi_driver = { /* Make sure we dont get a sg segment crosses a page boundary */ .dma_boundary = PAGE_SIZE-1, .no_write_same = 1, + .track_queue_depth = 1, }; enum { -- cgit v1.2.3 From 977965283526dd2e887331365da19b05c909a966 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 14 Dec 2016 18:45:59 -0800 Subject: scsi: storvsc: Remove the restriction on max segment size Remove the artificially imposed restriction on max segment size. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index ccb2101c6385..3b1c2f6528b4 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1267,8 +1267,6 @@ static int storvsc_do_io(struct hv_device *device, static int storvsc_device_configure(struct scsi_device *sdevice) { - blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); - blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY); blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ)); -- cgit v1.2.3 From d86adf482b843b3a58a9ec3b7c1ccdbf7c705db1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 14 Dec 2016 18:46:00 -0800 Subject: scsi: storvsc: Enable multi-queue support Enable multi-q support. We will allocate the outgoing channel using the following policy: 1. We will make every effort to pick a channel that is in the same NUMA node that is initiating the I/O 2. The mapping between the guest CPU and the outgoing channel is persistent. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 113 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3b1c2f6528b4..63f6b1ad57c5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -458,6 +458,15 @@ struct storvsc_device { * Max I/O, the device can support. */ u32 max_transfer_bytes; + /* + * Number of sub-channels we will open. + */ + u16 num_sc; + struct vmbus_channel **stor_chns; + /* + * Mask of CPUs bound to subchannels. + */ + struct cpumask alloced_cpus; /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; @@ -635,6 +644,11 @@ static void handle_sc_creation(struct vmbus_channel *new_sc) (void *)&props, sizeof(struct vmstorage_channel_properties), storvsc_on_channel_callback, new_sc); + + if (new_sc->state == CHANNEL_OPENED_STATE) { + 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) @@ -651,6 +665,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) if (!stor_device) return; + stor_device->num_sc = num_sc; request = &stor_device->init_request; vstor_packet = &request->vstor_packet; @@ -838,6 +853,25 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; + + /* + * Allocate state to manage the sub-channels. + * We allocate an array based on the numbers of possible CPUs + * (Hyper-V does not support cpu online/offline). + * This Array will be sparseley populated with unique + * channels - primary + sub-channels. + * We will however populate all the slots to evenly distribute + * the load. + */ + stor_device->stor_chns = kzalloc(sizeof(void *) * num_possible_cpus(), + GFP_KERNEL); + if (stor_device->stor_chns == NULL) + return -ENOMEM; + + stor_device->stor_chns[device->channel->target_cpu] = device->channel; + cpumask_set_cpu(device->channel->target_cpu, + &stor_device->alloced_cpus); + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) @@ -1198,17 +1232,64 @@ static int storvsc_dev_remove(struct hv_device *device) /* Close the channel */ vmbus_close(device->channel); + kfree(stor_device->stor_chns); kfree(stor_device); return 0; } +static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, + u16 q_num) +{ + u16 slot = 0; + u16 hash_qnum; + struct cpumask alloced_mask; + int num_channels, tgt_cpu; + + if (stor_device->num_sc == 0) + return stor_device->device->channel; + + /* + * Our channel array is sparsley populated and we + * initiated I/O on a processor/hw-q that does not + * currently have a designated channel. Fix this. + * The strategy is simple: + * I. Ensure NUMA locality + * II. Distribute evenly (best effort) + * III. Mapping is persistent. + */ + + cpumask_and(&alloced_mask, &stor_device->alloced_cpus, + cpumask_of_node(cpu_to_node(q_num))); + + num_channels = cpumask_weight(&alloced_mask); + if (num_channels == 0) + return stor_device->device->channel; + + hash_qnum = q_num; + while (hash_qnum >= num_channels) + hash_qnum -= num_channels; + + for_each_cpu(tgt_cpu, &alloced_mask) { + if (slot == hash_qnum) + break; + slot++; + } + + stor_device->stor_chns[q_num] = stor_device->stor_chns[tgt_cpu]; + + return stor_device->stor_chns[q_num]; +} + + static int storvsc_do_io(struct hv_device *device, - struct storvsc_cmd_request *request) + struct storvsc_cmd_request *request, u16 q_num) { struct storvsc_device *stor_device; struct vstor_packet *vstor_packet; struct vmbus_channel *outgoing_channel; int ret = 0; + struct cpumask alloced_mask; + int tgt_cpu; vstor_packet = &request->vstor_packet; stor_device = get_out_stor_device(device); @@ -1222,7 +1303,26 @@ static int storvsc_do_io(struct hv_device *device, * Select an an appropriate channel to send the request out. */ - outgoing_channel = vmbus_get_outgoing_channel(device->channel); + if (stor_device->stor_chns[q_num] != NULL) { + outgoing_channel = stor_device->stor_chns[q_num]; + if (outgoing_channel->target_cpu == smp_processor_id()) { + /* + * Ideally, we want to pick a different channel if + * available on the same NUMA node. + */ + cpumask_and(&alloced_mask, &stor_device->alloced_cpus, + cpumask_of_node(cpu_to_node(q_num))); + for_each_cpu(tgt_cpu, &alloced_mask) { + if (tgt_cpu != outgoing_channel->target_cpu) { + outgoing_channel = + stor_device->stor_chns[tgt_cpu]; + break; + } + } + } + } else { + outgoing_channel = get_og_chn(stor_device, q_num); + } vstor_packet->flags |= REQUEST_COMPLETION_FLAG; @@ -1522,7 +1622,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) cmd_request->payload_sz = payload_sz; /* Invokes the vsc to start an IO */ - ret = storvsc_do_io(dev, cmd_request); + ret = storvsc_do_io(dev, cmd_request, get_cpu()); + put_cpu(); if (ret == -EAGAIN) { /* no more space */ @@ -1679,6 +1780,11 @@ static int storvsc_probe(struct hv_device *device, * from the host. */ host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT); + /* + * Set the number of HW queues we are supporting. + */ + if (stor_device->num_sc != 0) + host->nr_hw_queues = stor_device->num_sc + 1; /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); @@ -1715,6 +1821,7 @@ err_out2: goto err_out0; err_out1: + kfree(stor_device->stor_chns); kfree(stor_device); err_out0: -- cgit v1.2.3 From 3cd6d3d9b1abab8dcdf0800224ce26daac24eea2 Mon Sep 17 00:00:00 2001 From: Long Li Date: Wed, 14 Dec 2016 18:46:01 -0800 Subject: scsi: storvsc: use tagged SRB requests if supported by the device Properly set SRB flags when hosting device supports tagged queuing. This patch improves the performance on Fiber Channel disks. Signed-off-by: Long Li Reviewed-by: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan Cc: Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 63f6b1ad57c5..320938720544 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -136,6 +136,8 @@ struct hv_fc_wwn_packet { #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 +#define SP_UNTAGGED ((unsigned char) ~0) +#define SRB_SIMPLE_TAG_REQUEST 0x20 /* * Platform neutral description of a scsi request - @@ -1549,6 +1551,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + if (scmnd->device->tagged_supported) { + vm_srb->win8_extension.srb_flags |= + (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); + vm_srb->win8_extension.queue_tag = SP_UNTAGGED; + vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; + } + /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: -- cgit v1.2.3 From bba5dc332ec2d3a685cb4dae668c793f6a3713a3 Mon Sep 17 00:00:00 2001 From: Long Li Date: Wed, 14 Dec 2016 18:46:02 -0800 Subject: scsi: storvsc: properly handle SRB_ERROR when sense message is present When sense message is present on error, we should pass along to the upper layer to decide how to deal with the error. This patch fixes connectivity issues with Fiber Channel devices. Signed-off-by: Long Li Reviewed-by: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan Cc: Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 320938720544..3c92dc2a25a0 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -924,6 +924,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, switch (SRB_STATUS(vm_srb->srb_status)) { case SRB_STATUS_ERROR: + /* + * Let upper layer deal with error when + * sense message is present. + */ + + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) + break; /* * If there is an error; offline the device since all * error recovery strategies would have already been -- cgit v1.2.3 From 40630f462824ee24bc00d692865c86c3828094e0 Mon Sep 17 00:00:00 2001 From: Long Li Date: Wed, 14 Dec 2016 18:46:03 -0800 Subject: scsi: storvsc: properly set residual data length on errors On I/O errors, the Windows driver doesn't set data_transfer_length on error conditions other than SRB_STATUS_DATA_OVERRUN. In these cases we need to set data_transfer_length to 0, indicating there is no data transferred. On SRB_STATUS_DATA_OVERRUN, data_transfer_length is set by the Windows driver to the actual data transferred. Reported-by: Shiva Krishna Signed-off-by: Long Li Reviewed-by: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan Cc: Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3c92dc2a25a0..888e16ec8554 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -377,6 +377,7 @@ enum storvsc_request_type { #define SRB_STATUS_SUCCESS 0x01 #define SRB_STATUS_ABORTED 0x02 #define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS_DATA_OVERRUN 0x12 #define SRB_STATUS(status) \ (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) @@ -996,6 +997,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, struct scsi_cmnd *scmnd = cmd_request->cmd; struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; + u32 data_transfer_length; struct Scsi_Host *host; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; @@ -1003,6 +1005,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, host = stor_dev->host; vm_srb = &cmd_request->vstor_packet.vm_srb; + data_transfer_length = vm_srb->data_transfer_length; scmnd->result = vm_srb->scsi_status; @@ -1016,13 +1019,20 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, &sense_hdr); } - if (vm_srb->srb_status != SRB_STATUS_SUCCESS) + if (vm_srb->srb_status != SRB_STATUS_SUCCESS) { storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, sense_hdr.ascq); + /* + * The Windows driver set data_transfer_length on + * SRB_STATUS_DATA_OVERRUN. On other errors, this value + * is untouched. In these cases we set it to 0. + */ + if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN) + data_transfer_length = 0; + } scsi_set_resid(scmnd, - cmd_request->payload->range.len - - vm_srb->data_transfer_length); + cmd_request->payload->range.len - data_transfer_length); scmnd->scsi_done(scmnd); -- cgit v1.2.3 From e0165f20447c8ca1d367725ee94d8ec9f38ca275 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:20 -0800 Subject: scsi: lpfc: Clear the VendorVersion in the PLOGI/PLOGI ACC payload Clear the VendorVersion in the PLOGI/PLOGI ACC payload Vendor version info may have been set on fabric login. Before sending PLOGI payloads, ensure that it's cleared. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 6 ++++++ drivers/scsi/lpfc/lpfc_hw.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 236e4e51d161..27f0cbb9b278 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1999,6 +1999,9 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) if (sp->cmn.fcphHigh < FC_PH3) sp->cmn.fcphHigh = FC_PH3; + sp->cmn.valid_vendor_ver_level = 0; + memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue PLOGI: did:x%x", did, 0, 0); @@ -3988,6 +3991,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, } else { memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm)); + + sp->cmn.valid_vendor_ver_level = 0; + memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 822654322e67..3b970d370600 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -360,6 +360,12 @@ struct csp { * Word 1 Bit 30 in PLOGI request is random offset */ #define virtual_fabric_support randomOffset /* Word 1, bit 30 */ +/* + * Word 1 Bit 29 in common service parameter is overloaded. + * Word 1 Bit 29 in FLOGI response is multiple NPort assignment + * Word 1 Bit 29 in FLOGI/PLOGI request is Valid Vendor Version Level + */ +#define valid_vendor_ver_level response_multiple_NPort /* Word 1, bit 29 */ #ifdef __BIG_ENDIAN_BITFIELD uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ uint16_t randomOffset:1; /* FC Word 1, bit 30 */ -- cgit v1.2.3 From b2fd103b05feabbc86db726ae121da94639892d7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:21 -0800 Subject: scsi: lpfc: Correct error in setting OS Driver Version with FW Correct error in setting OS Driver Version with FW. Prior length was too short. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4faa7672fc1d..f895cb9c89a3 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -6306,7 +6306,8 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) LPFC_SLI4_MBX_EMBED); mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION; - mbox->u.mqe.un.set_host_data.param_len = 8; + mbox->u.mqe.un.set_host_data.param_len = + LPFC_HOST_OS_DRIVER_VERSION_SIZE; snprintf(mbox->u.mqe.un.set_host_data.data, LPFC_HOST_OS_DRIVER_VERSION_SIZE, "Linux %s v"LPFC_DRIVER_VERSION, -- cgit v1.2.3 From 8c6a6f4076984ab15c33c2a52a10b681359f5a2a Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:22 -0800 Subject: scsi: lpfc: Deprecate lpfc_soft_wwn parameter Deprecate lpfc_soft_wwn parameter. No longer allow override of hw-assigned wwns Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 4 - drivers/scsi/lpfc/lpfc_attr.c | 216 ------------------------------------------ drivers/scsi/lpfc/lpfc_init.c | 16 +--- 3 files changed, 3 insertions(+), 233 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 8a20b4e86224..341b656e9d9d 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -729,8 +729,6 @@ struct lpfc_hba { uint32_t cfg_sg_seg_cnt; uint32_t cfg_prot_sg_seg_cnt; uint32_t cfg_sg_dma_buf_size; - uint64_t cfg_soft_wwnn; - uint64_t cfg_soft_wwpn; uint32_t cfg_hba_queue_depth; uint32_t cfg_enable_hba_reset; uint32_t cfg_enable_hba_heartbeat; @@ -835,8 +833,6 @@ struct lpfc_hba { #define VPD_PORT 0x8 /* valid vpd port data */ #define VPD_MASK 0xf /* mask for any vpd data */ - uint8_t soft_wwn_enable; - struct timer_list fcp_poll_timer; struct timer_list eratt_poll; uint32_t eratt_poll_interval; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c84775562c65..98c40a734a36 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1987,7 +1987,6 @@ static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show, NULL); -static char *lpfc_soft_wwn_key = "C99G71SL8032A"; #define WWN_SZ 8 /** * lpfc_wwn_set - Convert string to the 8 byte WWN value. @@ -2031,216 +2030,6 @@ lpfc_wwn_set(const char *buf, size_t cnt, char wwn[]) } return 0; } -/** - * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: containing the string lpfc_soft_wwn_key. - * @count: must be size of lpfc_soft_wwn_key. - * - * Returns: - * -EINVAL if the buffer does not contain lpfc_soft_wwn_key - * length of buf indicates success - **/ -static ssize_t -lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - unsigned int cnt = count; - - /* - * We're doing a simple sanity check for soft_wwpn setting. - * We require that the user write a specific key to enable - * the soft_wwpn attribute to be settable. Once the attribute - * is written, the enable key resets. If further updates are - * desired, the key must be written again to re-enable the - * attribute. - * - * The "key" is not secret - it is a hardcoded string shown - * here. The intent is to protect against the random user or - * application that is just writing attributes. - */ - - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if ((cnt != strlen(lpfc_soft_wwn_key)) || - (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0)) - return -EINVAL; - - phba->soft_wwn_enable = 1; - return count; -} -static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, - lpfc_soft_wwn_enable_store); - -/** - * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: on return contains the wwpn in hexadecimal. - * - * Returns: size of formatted string. - **/ -static ssize_t -lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - - return snprintf(buf, PAGE_SIZE, "0x%llx\n", - (unsigned long long)phba->cfg_soft_wwpn); -} - -/** - * lpfc_soft_wwpn_store - Set the ww port name of the adapter - * @dev class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: contains the wwpn in hexadecimal. - * @count: number of wwpn bytes in buf - * - * Returns: - * -EACCES hba reset not enabled, adapter over temp - * -EINVAL soft wwn not enabled, count is invalid, invalid wwpn byte invalid - * -EIO error taking adapter offline or online - * value of count on success - **/ -static ssize_t -lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - struct completion online_compl; - int stat1 = 0, stat2 = 0; - unsigned int cnt = count; - u8 wwpn[WWN_SZ]; - int rc; - - if (!phba->cfg_enable_hba_reset) - return -EACCES; - spin_lock_irq(&phba->hbalock); - if (phba->over_temp_state == HBA_OVER_TEMP) { - spin_unlock_irq(&phba->hbalock); - return -EACCES; - } - spin_unlock_irq(&phba->hbalock); - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if (!phba->soft_wwn_enable) - return -EINVAL; - - /* lock setting wwpn, wwnn down */ - phba->soft_wwn_enable = 0; - - rc = lpfc_wwn_set(buf, cnt, wwpn); - if (!rc) { - /* not able to set wwpn, unlock it */ - phba->soft_wwn_enable = 1; - return rc; - } - - phba->cfg_soft_wwpn = wwn_to_u64(wwpn); - fc_host_port_name(shost) = phba->cfg_soft_wwpn; - if (phba->cfg_soft_wwnn) - fc_host_node_name(shost) = phba->cfg_soft_wwnn; - - dev_printk(KERN_NOTICE, &phba->pcidev->dev, - "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); - - stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); - if (stat1) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0463 lpfc_soft_wwpn attribute set failed to " - "reinit adapter - %d\n", stat1); - init_completion(&online_compl); - rc = lpfc_workq_post_event(phba, &stat2, &online_compl, - LPFC_EVT_ONLINE); - if (rc == 0) - return -ENOMEM; - - wait_for_completion(&online_compl); - if (stat2) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0464 lpfc_soft_wwpn attribute set failed to " - "reinit adapter - %d\n", stat2); - return (stat1 || stat2) ? -EIO : count; -} -static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR, - lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); - -/** - * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter - * @dev: class device that is converted into a Scsi_host. - * @attr: device attribute, not used. - * @buf: on return contains the wwnn in hexadecimal. - * - * Returns: size of formatted string. - **/ -static ssize_t -lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; - return snprintf(buf, PAGE_SIZE, "0x%llx\n", - (unsigned long long)phba->cfg_soft_wwnn); -} - -/** - * lpfc_soft_wwnn_store - sets the ww node name of the adapter - * @cdev: class device that is converted into a Scsi_host. - * @buf: contains the ww node name in hexadecimal. - * @count: number of wwnn bytes in buf. - * - * Returns: - * -EINVAL soft wwn not enabled, count is invalid, invalid wwnn byte invalid - * value of count on success - **/ -static ssize_t -lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; - unsigned int cnt = count; - u8 wwnn[WWN_SZ]; - int rc; - - /* count may include a LF at end of string */ - if (buf[cnt-1] == '\n') - cnt--; - - if (!phba->soft_wwn_enable) - return -EINVAL; - - rc = lpfc_wwn_set(buf, cnt, wwnn); - if (!rc) { - /* Allow wwnn to be set many times, as long as the enable - * is set. However, once the wwpn is set, everything locks. - */ - return rc; - } - - phba->cfg_soft_wwnn = wwn_to_u64(wwnn); - - dev_printk(KERN_NOTICE, &phba->pcidev->dev, - "lpfc%d: soft_wwnn set. Value will take effect upon " - "setting of the soft_wwpn\n", phba->brd_no); - - return count; -} -static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR, - lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); /** * lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for @@ -4750,9 +4539,6 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_fcp_cpu_map, &dev_attr_lpfc_fcp_io_channel, &dev_attr_lpfc_enable_bg, - &dev_attr_lpfc_soft_wwnn, - &dev_attr_lpfc_soft_wwpn, - &dev_attr_lpfc_soft_wwn_enable, &dev_attr_lpfc_enable_hba_reset, &dev_attr_lpfc_enable_hba_heartbeat, &dev_attr_lpfc_EnableXLane, @@ -5765,8 +5551,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) else phba->cfg_poll = lpfc_poll; - phba->cfg_soft_wwnn = 0L; - phba->cfg_soft_wwpn = 0L; lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); lpfc_prot_sg_seg_cnt_init(phba, lpfc_prot_sg_seg_cnt); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4776fd85514f..43d2b06bdc82 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -319,36 +319,26 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /** * lpfc_update_vport_wwn - Updates the fc_nodename, fc_portname, - * cfg_soft_wwnn, cfg_soft_wwpn * @vport: pointer to lpfc vport data structure. * - * * Return codes * None. **/ void lpfc_update_vport_wwn(struct lpfc_vport *vport) { - /* If the soft name exists then update it using the service params */ - if (vport->phba->cfg_soft_wwnn) - u64_to_wwn(vport->phba->cfg_soft_wwnn, - vport->fc_sparam.nodeName.u.wwn); - if (vport->phba->cfg_soft_wwpn) - u64_to_wwn(vport->phba->cfg_soft_wwpn, - vport->fc_sparam.portName.u.wwn); - /* - * If the name is empty or there exists a soft name + * If the name is empty * then copy the service params name, otherwise use the fc name */ - if (vport->fc_nodename.u.wwn[0] == 0 || vport->phba->cfg_soft_wwnn) + if (vport->fc_nodename.u.wwn[0] == 0) memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); else memcpy(&vport->fc_sparam.nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); - if (vport->fc_portname.u.wwn[0] == 0 || vport->phba->cfg_soft_wwpn) + if (vport->fc_portname.u.wwn[0] == 0) memcpy(&vport->fc_portname, &vport->fc_sparam.portName, sizeof(struct lpfc_name)); else -- cgit v1.2.3 From e6c6acc0e0223ddaf867628d420ee196349c6fae Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:23 -0800 Subject: scsi: lpfc: Correct issue leading to oops during link reset Correct issue leading to oops during link reset. Missing vport pointer. [mkp: fixed typo] Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f895cb9c89a3..6b75a8fced33 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10029,6 +10029,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, iabt->ulpCommand = CMD_CLOSE_XRI_CN; abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; + abtsiocbp->vport = vport; lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, "0339 Abort xri x%x, original iotag x%x, " -- cgit v1.2.3 From 6c9231f604c2575be24c96d38deb70f145172f92 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:24 -0800 Subject: scsi: lpfc: Correct host name in symbolic_name field Correct host name in symbolic_name field of nameserver registrations Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 98c40a734a36..f3250ad6b3eb 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4846,6 +4846,19 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) * Dynamic FC Host Attributes Support */ +/** + * lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host + * @shost: kernel scsi host pointer. + **/ +static void +lpfc_get_host_symbolic_name(struct Scsi_Host *shost) +{ + struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; + + lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost), + sizeof fc_host_symbolic_name(shost)); +} + /** * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id * @shost: kernel scsi host pointer. @@ -5383,6 +5396,8 @@ struct fc_function_template lpfc_transport_functions = { .show_host_supported_fc4s = 1, .show_host_supported_speeds = 1, .show_host_maxframe_size = 1, + + .get_host_symbolic_name = lpfc_get_host_symbolic_name, .show_host_symbolic_name = 1, /* dynamic attributes the driver supports */ @@ -5450,6 +5465,8 @@ struct fc_function_template lpfc_vport_transport_functions = { .show_host_supported_fc4s = 1, .show_host_supported_speeds = 1, .show_host_maxframe_size = 1, + + .get_host_symbolic_name = lpfc_get_host_symbolic_name, .show_host_symbolic_name = 1, /* dynamic attributes the driver supports */ -- cgit v1.2.3 From 104450eb08ca662e6b1d02da11aca9598e978f3e Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:25 -0800 Subject: scsi: lpfc: FCoE VPort enable-disable does not bring up the VPort FCoE VPort enable-disable does not bring up the VPort. VPI structure needed to be initialized before being re-registered. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_vport.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index c27f4b724547..e18bbc66e83b 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -537,6 +537,12 @@ enable_vport(struct fc_vport *fc_vport) spin_lock_irq(shost->host_lock); vport->load_flag |= FC_LOADING; + if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) { + spin_unlock_irq(shost->host_lock); + lpfc_issue_init_vpi(vport); + goto out; + } + vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; spin_unlock_irq(shost->host_lock); @@ -557,6 +563,8 @@ enable_vport(struct fc_vport *fc_vport) } else { lpfc_vport_set_state(vport, FC_VPORT_FAILED); } + +out: lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, "1827 Vport Enabled.\n"); return VPORT_OK; -- cgit v1.2.3 From b5749fe182a0fa1c39ea1b33c0691d436f269195 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:26 -0800 Subject: scsi: lpfc: Fix Xlane dynamic LUN set for LUN priority. Fix Xlane dynamic LUN set for LUN priority. Dynamic changing of the priority was not getting reflected on the LUN. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 23 +++++++++++++++-------- drivers/scsi/lpfc/lpfc_crtn.h | 7 ++++--- drivers/scsi/lpfc/lpfc_scsi.c | 18 ++++++++++++------ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index f3250ad6b3eb..c30fafe3bb31 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2224,7 +2224,8 @@ lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr, else phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT; phba->cfg_oas_flags &= ~OAS_LUN_VALID; - phba->cfg_oas_priority = phba->cfg_XLanePriority; + if (phba->cfg_oas_priority == 0) + phba->cfg_oas_priority = phba->cfg_XLanePriority; phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN; return count; } @@ -2350,7 +2351,7 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], rc = -ENOMEM; } else { lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn, - (struct lpfc_name *)tgt_wwpn, lun); + (struct lpfc_name *)tgt_wwpn, lun, pri); } return rc; @@ -2374,7 +2375,8 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], */ static uint64_t lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], - uint8_t tgt_wwpn[], uint32_t *lun_status) + uint8_t tgt_wwpn[], uint32_t *lun_status, + uint32_t *lun_pri) { uint64_t found_lun; @@ -2387,7 +2389,7 @@ lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], &phba->sli4_hba.oas_next_lun, (struct lpfc_name *)vpt_wwpn, (struct lpfc_name *)tgt_wwpn, - &found_lun, lun_status)) + &found_lun, lun_status, lun_pri)) return found_lun; else return NOT_OAS_ENABLED_LUN; @@ -2459,7 +2461,8 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr, oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn, phba->cfg_oas_tgt_wwpn, - &phba->cfg_oas_lun_status); + &phba->cfg_oas_lun_status, + &phba->cfg_oas_priority); if (oas_lun != NOT_OAS_ENABLED_LUN) phba->cfg_oas_flags |= OAS_LUN_VALID; @@ -2490,6 +2493,7 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; uint64_t scsi_lun; + uint32_t pri; ssize_t rc; if (!phba->cfg_fof) @@ -2507,17 +2511,20 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr, if (sscanf(buf, "0x%llx", &scsi_lun) != 1) return -EINVAL; + pri = phba->cfg_oas_priority; + if (pri == 0) + pri = phba->cfg_XLanePriority; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx " "priority 0x%x with oas state %d\n", wwn_to_u64(phba->cfg_oas_vpt_wwpn), wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun, - phba->cfg_oas_priority, phba->cfg_oas_lun_state); + pri, phba->cfg_oas_lun_state); rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn, phba->cfg_oas_tgt_wwpn, scsi_lun, - phba->cfg_oas_lun_state, - phba->cfg_oas_priority); + phba->cfg_oas_lun_state, pri); if (rc) return rc; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 15d2bfdf582d..309643a2c55c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -480,7 +480,7 @@ void lpfc_sli4_offline_eratt(struct lpfc_hba *); struct lpfc_device_data *lpfc_create_device_data(struct lpfc_hba *, struct lpfc_name *, struct lpfc_name *, - uint64_t, bool); + uint64_t, uint32_t, bool); void lpfc_delete_device_data(struct lpfc_hba *, struct lpfc_device_data*); struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *, struct list_head *list, @@ -489,9 +489,10 @@ struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *, bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *, struct lpfc_name *, uint64_t, uint8_t); bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *, - struct lpfc_name *, uint64_t); + struct lpfc_name *, uint64_t, uint8_t); bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *, struct lpfc_name *, uint64_t *, struct lpfc_name *, - struct lpfc_name *, uint64_t *, uint32_t *); + struct lpfc_name *, uint64_t *, + uint32_t *, uint32_t *); int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox); void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index ad350d969bdc..19d349fc889f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5452,7 +5452,9 @@ lpfc_slave_alloc(struct scsi_device *sdev) device_data = lpfc_create_device_data(phba, &vport->fc_portname, &target_wwpn, - sdev->lun, true); + sdev->lun, + phba->cfg_XLanePriority, + true); if (!device_data) return -ENOMEM; spin_lock_irqsave(&phba->devicelock, flags); @@ -5587,7 +5589,7 @@ lpfc_slave_destroy(struct scsi_device *sdev) struct lpfc_device_data* lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, struct lpfc_name *target_wwpn, uint64_t lun, - bool atomic_create) + uint32_t pri, bool atomic_create) { struct lpfc_device_data *lun_info; @@ -5614,7 +5616,7 @@ lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, sizeof(struct lpfc_name)); lun_info->device_id.lun = lun; lun_info->oas_enabled = false; - lun_info->priority = phba->cfg_XLanePriority; + lun_info->priority = pri; lun_info->available = false; return lun_info; } @@ -5716,7 +5718,8 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, struct lpfc_name *found_vport_wwpn, struct lpfc_name *found_target_wwpn, uint64_t *found_lun, - uint32_t *found_lun_status) + uint32_t *found_lun_status, + uint32_t *found_lun_pri) { unsigned long flags; @@ -5763,6 +5766,7 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, OAS_LUN_STATUS_EXISTS; else *found_lun_status = 0; + *found_lun_pri = lun_info->priority; if (phba->cfg_oas_flags & OAS_FIND_ANY_VPORT) memset(vport_wwpn, 0x0, sizeof(struct lpfc_name)); @@ -5824,13 +5828,14 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, if (lun_info) { if (!lun_info->oas_enabled) lun_info->oas_enabled = true; + lun_info->priority = pri; spin_unlock_irqrestore(&phba->devicelock, flags); return true; } /* Create an lun info structure and add to list of luns */ lun_info = lpfc_create_device_data(phba, vport_wwpn, target_wwpn, lun, - false); + pri, false); if (lun_info) { lun_info->oas_enabled = true; lun_info->priority = pri; @@ -5864,7 +5869,7 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, **/ bool lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, - struct lpfc_name *target_wwpn, uint64_t lun) + struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri) { struct lpfc_device_data *lun_info; @@ -5882,6 +5887,7 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, target_wwpn, lun); if (lun_info) { lun_info->oas_enabled = false; + lun_info->priority = pri; if (!lun_info->available) lpfc_delete_device_data(phba, lun_info); spin_unlock_irqrestore(&phba->devicelock, flags); -- cgit v1.2.3 From f2bf460cf5ef989f0a593d05932460326376d5f6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:27 -0800 Subject: scsi: lpfc: Deprecate lpfc_prot_sg_seg_cnt parameter Deprecate lpfc_prot_sg_seg_cnt parameter. Eliminates driver from unnecessarily limiting DIF s/g list length. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 - drivers/scsi/lpfc/lpfc_attr.c | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 341b656e9d9d..c2e6ffd2f372 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -727,7 +727,6 @@ struct lpfc_hba { uint32_t cfg_fcp_io_channel; uint32_t cfg_total_seg_cnt; uint32_t cfg_sg_seg_cnt; - uint32_t cfg_prot_sg_seg_cnt; uint32_t cfg_sg_dma_buf_size; uint32_t cfg_hba_queue_depth; uint32_t cfg_enable_hba_reset; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c30fafe3bb31..8301c08b8768 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4465,14 +4465,6 @@ LPFC_ATTR(delay_discovery, 0, 0, 1, LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); -/* - * This parameter will be depricated, the driver cannot limit the - * protection data s/g list. - */ -LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, - LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, - "Max Protection Scatter Gather Segment Count"); - /* * lpfc_enable_mds_diags: Enable MDS Diagnostics * 0 = MDS Diagnostics disabled (default) @@ -4559,7 +4551,6 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_sg_seg_cnt, &dev_attr_lpfc_max_scsicmpl_time, &dev_attr_lpfc_stat_data_ctrl, - &dev_attr_lpfc_prot_sg_seg_cnt, &dev_attr_lpfc_aer_support, &dev_attr_lpfc_aer_state_cleanup, &dev_attr_lpfc_sriov_nr_virtfn, @@ -5576,7 +5567,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_poll = lpfc_poll; lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); - lpfc_prot_sg_seg_cnt_init(phba, lpfc_prot_sg_seg_cnt); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); lpfc_aer_support_init(phba, lpfc_aer_support); -- cgit v1.2.3 From 2f07784f05c23b322863274e801c31aa64e46c71 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:29 -0800 Subject: scsi: lpfc: Correct oops on vport port resets Correct oops on vport port resets. Incorrect WQE type, thus the clearing code actually overstepped the WQE. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 6b75a8fced33..7e11cbdb238c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -17221,7 +17221,8 @@ lpfc_drain_txq(struct lpfc_hba *phba) unsigned long iflags = 0; char *fail_msg = NULL; struct lpfc_sglq *sglq; - union lpfc_wqe wqe; + union lpfc_wqe128 wqe128; + union lpfc_wqe *wqe = (union lpfc_wqe *) &wqe128; uint32_t txq_cnt = 0; spin_lock_irqsave(&pring->ring_lock, iflags); @@ -17260,9 +17261,9 @@ lpfc_drain_txq(struct lpfc_hba *phba) piocbq->sli4_xritag = sglq->sli4_xritag; if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) fail_msg = "to convert bpl to sgl"; - else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) + else if (lpfc_sli4_iocb2wqe(phba, piocbq, wqe)) fail_msg = "to convert iocb to wqe"; - else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) + else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe)) fail_msg = " - Wq is full"; else lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); -- cgit v1.2.3 From 6b3b3bdb83b4ad51252d21bb13596db879e51850 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:30 -0800 Subject: scsi: lpfc: Add missing memory barrier On loosely ordered memory systems (PPC for example), the WQE elements were being updated in memory, but not necessarily flushed before the separate doorbell was written to hw which would cause hw to dma the WQE element. Thus, the hardware occasionally received partially updated WQE data. Add the memory barrier after updating the WQE memory. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7e11cbdb238c..3a8470d55af5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -120,6 +120,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); + /* ensure WQE bcopy flushed before doorbell write */ + wmb(); /* Update the host index before invoking device */ host_index = q->host_index; -- cgit v1.2.3 From 4b089d18ed979d91424355b117070f2520f85aeb Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 19 Dec 2016 15:07:31 -0800 Subject: scsi: lpfc: lpfc version change to 11.2.0.4 lpfc version change to 11.2.0.4 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 50bfc43ebcb0..0ee0623a354c 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.2.0.2" +#define LPFC_DRIVER_VERSION "11.2.0.4" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- cgit v1.2.3 From 93380123fbb5357d3ea6935efc9226df3c59099d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 16 Dec 2016 17:04:49 -0800 Subject: scsi: hpsa: use designated initializers Prepare to mark sensitive kernel structures for randomization by making sure they're using designated initializers. These were identified during allyesconfig builds of x86, arm, and arm64, with most initializer fixes extracted from grsecurity. Signed-off-by: Kees Cook Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 64e98295b707..bf6cdc106654 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -578,38 +578,38 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) } static struct access_method SA5_access = { - SA5_submit_command, - SA5_intr_mask, - SA5_intr_pending, - SA5_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5_intr_mask, + .intr_pending = SA5_intr_pending, + .command_completed = SA5_completed, }; static struct access_method SA5_ioaccel_mode1_access = { - SA5_submit_command, - SA5_performant_intr_mask, - SA5_ioaccel_mode1_intr_pending, - SA5_ioaccel_mode1_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5_performant_intr_mask, + .intr_pending = SA5_ioaccel_mode1_intr_pending, + .command_completed = SA5_ioaccel_mode1_completed, }; static struct access_method SA5_ioaccel_mode2_access = { - SA5_submit_command_ioaccel2, - SA5_performant_intr_mask, - SA5_performant_intr_pending, - SA5_performant_completed, + .submit_command = SA5_submit_command_ioaccel2, + .set_intr_mask = SA5_performant_intr_mask, + .intr_pending = SA5_performant_intr_pending, + .command_completed = SA5_performant_completed, }; static struct access_method SA5_performant_access = { - SA5_submit_command, - SA5_performant_intr_mask, - SA5_performant_intr_pending, - SA5_performant_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5_performant_intr_mask, + .intr_pending = SA5_performant_intr_pending, + .command_completed = SA5_performant_completed, }; static struct access_method SA5_performant_access_no_read = { - SA5_submit_command_no_read, - SA5_performant_intr_mask, - SA5_performant_intr_pending, - SA5_performant_completed, + .submit_command = SA5_submit_command_no_read, + .set_intr_mask = SA5_performant_intr_mask, + .intr_pending = SA5_performant_intr_pending, + .command_completed = SA5_performant_completed, }; struct board_type { -- cgit v1.2.3 From 5f5fca6db3d3e6a2c1a2ae92cbecee50e1242a3a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 16 Dec 2016 17:05:30 -0800 Subject: scsi: cciss: use designated initializers Prepare to mark sensitive kernel structures for randomization by making sure they're using designated initializers. These were identified during allyesconfig builds of x86, arm, and arm64, with most initializer fixes extracted from grsecurity. Signed-off-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/block/cciss.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 7fda30e4a241..428766d1ce80 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -402,27 +402,27 @@ static bool SA5_performant_intr_pending(ctlr_info_t *h) } static struct access_method SA5_access = { - SA5_submit_command, - SA5_intr_mask, - SA5_fifo_full, - SA5_intr_pending, - SA5_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5_intr_mask, + .fifo_full = SA5_fifo_full, + .intr_pending = SA5_intr_pending, + .command_completed = SA5_completed, }; static struct access_method SA5B_access = { - SA5_submit_command, - SA5B_intr_mask, - SA5_fifo_full, - SA5B_intr_pending, - SA5_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5B_intr_mask, + .fifo_full = SA5_fifo_full, + .intr_pending = SA5B_intr_pending, + .command_completed = SA5_completed, }; static struct access_method SA5_performant_access = { - SA5_submit_command, - SA5_performant_intr_mask, - SA5_fifo_full, - SA5_performant_intr_pending, - SA5_performant_completed, + .submit_command = SA5_submit_command, + .set_intr_mask = SA5_performant_intr_mask, + .fifo_full = SA5_fifo_full, + .intr_pending = SA5_performant_intr_pending, + .command_completed = SA5_performant_completed, }; struct board_type { -- cgit v1.2.3 From e0075478ca7c58c6ad6630310aaa3f64a25dcf31 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Thu, 15 Dec 2016 15:12:16 +0100 Subject: scsi: mptlan: Remove linux/miscdevice.h from mptlan.h This patch remove linux/miscdevice.h from mptlan.h since mptlan.h does not contain any miscdevice. The only user of it is mptctl.c which already include linux/miscdevice.h So no need to include it twice. Signed-off-by: Corentin Labbe Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptlan.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 8946e19dbfc8..8a24494f8c4d 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -65,7 +65,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 19099dc393f3ca1fd9690f914e50278cf2aee78a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 16 Dec 2016 12:35:39 +0300 Subject: scsi: dpt_i2o: double free if adpt_i2o_online_hba() fails There are two places where adpt_i2o_online_hba() is called. Both callers call adpt_i2o_delete_hba(pHba) if adpt_i2o_online_hba() fails and since we also free it here that causes a double free bug. Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 5f75e638ec95..256dd6791fcc 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -2768,16 +2768,12 @@ static int adpt_i2o_activate_hba(adpt_hba* pHba) static int adpt_i2o_online_hba(adpt_hba* pHba) { - if (adpt_i2o_systab_send(pHba) < 0) { - adpt_i2o_delete_hba(pHba); + if (adpt_i2o_systab_send(pHba) < 0) return -1; - } /* In READY state */ - if (adpt_i2o_enable_hba(pHba) < 0) { - adpt_i2o_delete_hba(pHba); + if (adpt_i2o_enable_hba(pHba) < 0) return -1; - } /* In OPERATIONAL state */ return 0; -- cgit v1.2.3 From f3505013779646704f81b41c011ab089b26c3f3e Mon Sep 17 00:00:00 2001 From: Jitendra Bhivare Date: Tue, 13 Dec 2016 15:55:54 +0530 Subject: scsi: be2iscsi: Fix use of invalidate command table req Remove shared structure inv_tbl in phba for all sessions to post invalidation IOCTL. Always allocate and then free the table after use in reset handler. Abort handler needs just one instance so define it on stack. Add checks for BE_INVLDT_CMD_TBL_SZ to not exceed invalidation command table size in IOCTL. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/be2iscsi/be_main.c | 85 ++++++++++++++++++++++++----------------- drivers/scsi/be2iscsi/be_main.h | 16 ++++---- drivers/scsi/be2iscsi/be_mgmt.c | 12 +++--- drivers/scsi/be2iscsi/be_mgmt.h | 40 +++++++++---------- 4 files changed, 83 insertions(+), 70 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b5112d6d7e73..3811a0d230f2 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -225,9 +225,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) struct beiscsi_conn *beiscsi_conn; struct beiscsi_hba *phba; struct iscsi_session *session; - struct invalidate_command_table *inv_tbl; + struct invldt_cmd_tbl inv_tbl; struct be_dma_mem nonemb_cmd; - unsigned int cid, tag, num_invalidate; + unsigned int cid, tag; int rc; cls_session = starget_to_session(scsi_target(sc->device)); @@ -247,35 +247,30 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) return SUCCESS; } spin_unlock_bh(&session->frwd_lock); - /* Invalidate WRB Posted for this Task */ - AMAP_SET_BITS(struct amap_iscsi_wrb, invld, - aborted_io_task->pwrb_handle->pwrb, - 1); conn = aborted_task->conn; beiscsi_conn = conn->dd_data; phba = beiscsi_conn->phba; - + /* Invalidate WRB Posted for this Task */ + AMAP_SET_BITS(struct amap_iscsi_wrb, invld, + aborted_io_task->pwrb_handle->pwrb, + 1); /* invalidate iocb */ cid = beiscsi_conn->beiscsi_conn_cid; - inv_tbl = phba->inv_tbl; - memset(inv_tbl, 0x0, sizeof(*inv_tbl)); - inv_tbl->cid = cid; - inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; - num_invalidate = 1; - nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, - sizeof(struct invalidate_commands_params_in), - &nonemb_cmd.dma); + inv_tbl.cid = cid; + inv_tbl.icd = aborted_io_task->psgl_handle->sgl_index; + nonemb_cmd.size = sizeof(union be_invldt_cmds_params); + nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, + nonemb_cmd.size, + &nonemb_cmd.dma); if (nonemb_cmd.va == NULL) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, "BM_%d : Failed to allocate memory for" "mgmt_invalidate_icds\n"); return FAILED; } - nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); - tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, - cid, &nonemb_cmd); + tag = mgmt_invalidate_icds(phba, &inv_tbl, 1, cid, &nonemb_cmd); if (!tag) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, "BM_%d : mgmt_invalidate_icds could not be" @@ -303,10 +298,10 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) struct beiscsi_hba *phba; struct iscsi_session *session; struct iscsi_cls_session *cls_session; - struct invalidate_command_table *inv_tbl; + struct invldt_cmd_tbl *inv_tbl; struct be_dma_mem nonemb_cmd; - unsigned int cid, tag, i, num_invalidate; - int rc; + unsigned int cid, tag, i, nents; + int rc, more = 0; /* invalidate iocbs */ cls_session = starget_to_session(scsi_target(sc->device)); @@ -320,9 +315,15 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) beiscsi_conn = conn->dd_data; phba = beiscsi_conn->phba; cid = beiscsi_conn->beiscsi_conn_cid; - inv_tbl = phba->inv_tbl; - memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); - num_invalidate = 0; + + inv_tbl = kcalloc(BE_INVLDT_CMD_TBL_SZ, sizeof(*inv_tbl), GFP_KERNEL); + if (!inv_tbl) { + spin_unlock_bh(&session->frwd_lock); + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, + "BM_%d : invldt_cmd_tbl alloc failed\n"); + return FAILED; + } + nents = 0; for (i = 0; i < conn->session->cmds_max; i++) { abrt_task = conn->session->cmds[i]; abrt_io_task = abrt_task->dd_data; @@ -331,33 +332,47 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) if (sc->device->lun != abrt_task->sc->device->lun) continue; + /** + * Can't fit in more cmds? Normally this won't happen b'coz + * BEISCSI_CMD_PER_LUN is same as BE_INVLDT_CMD_TBL_SZ. + */ + if (nents == BE_INVLDT_CMD_TBL_SZ) { + more = 1; + break; + } /* Invalidate WRB Posted for this Task */ AMAP_SET_BITS(struct amap_iscsi_wrb, invld, abrt_io_task->pwrb_handle->pwrb, 1); - inv_tbl->cid = cid; - inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; - num_invalidate++; - inv_tbl++; + inv_tbl[nents].cid = cid; + inv_tbl[nents].icd = abrt_io_task->psgl_handle->sgl_index; + nents++; } spin_unlock_bh(&session->frwd_lock); - inv_tbl = phba->inv_tbl; - nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, - sizeof(struct invalidate_commands_params_in), - &nonemb_cmd.dma); + if (more) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, + "BM_%d : number of cmds exceeds size of invalidation table\n"); + kfree(inv_tbl); + return FAILED; + } + + nonemb_cmd.size = sizeof(union be_invldt_cmds_params); + nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, + nonemb_cmd.size, + &nonemb_cmd.dma); if (nonemb_cmd.va == NULL) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, "BM_%d : Failed to allocate memory for" "mgmt_invalidate_icds\n"); + kfree(inv_tbl); return FAILED; } - nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); - memset(nonemb_cmd.va, 0, nonemb_cmd.size); - tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, + tag = mgmt_invalidate_icds(phba, inv_tbl, nents, cid, &nonemb_cmd); + kfree(inv_tbl); if (!tag) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, "BM_%d : mgmt_invalidate_icds could not be" diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 6376657e45f7..f869e3734c02 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -57,7 +57,6 @@ #define BE2_IO_DEPTH 1024 #define BE2_MAX_SESSIONS 256 -#define BE2_CMDS_PER_CXN 128 #define BE2_TMFS 16 #define BE2_NOPOUT_REQ 16 #define BE2_SGE 32 @@ -72,8 +71,13 @@ #define BEISCSI_SGLIST_ELEMENTS 30 -#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ -#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ +/** + * BE_INVLDT_CMD_TBL_SZ is 128 which is total number commands that can + * be invalidated at a time, consider it before changing the value of + * BEISCSI_CMD_PER_LUN. + */ +#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ +#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ @@ -272,11 +276,6 @@ struct hba_parameters { unsigned int num_sge; }; -struct invalidate_command_table { - unsigned short icd; - unsigned short cid; -} __packed; - #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ (phwi_ctrlr->wrb_context[cri].ulp_num) struct hwi_wrb_context { @@ -430,7 +429,6 @@ struct beiscsi_hba { struct be_ctrl_info ctrl; unsigned int generation; unsigned int interface_handle; - struct invalidate_command_table inv_tbl[128]; struct be_aic_obj aic_obj[MAX_CPUS]; unsigned int attr_log_enable; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index ac05317bba7f..5f02e8db7df0 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -129,7 +129,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, } unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, - struct invalidate_command_table *inv_tbl, + struct invldt_cmd_tbl *inv_tbl, unsigned int num_invalidate, unsigned int cid, struct be_dma_mem *nonemb_cmd) @@ -137,9 +137,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, struct be_ctrl_info *ctrl = &phba->ctrl; struct be_mcc_wrb *wrb; struct be_sge *sge; - struct invalidate_commands_params_in *req; + struct invldt_cmds_params_in *req; unsigned int i, tag; + if (num_invalidate > BE_INVLDT_CMD_TBL_SZ) + return 0; + mutex_lock(&ctrl->mbox_lock); wrb = alloc_mcc_wrb(phba, &tag); if (!wrb) { @@ -158,10 +161,9 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, req->ref_handle = 0; req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; for (i = 0; i < num_invalidate; i++) { - req->table[i].icd = inv_tbl->icd; - req->table[i].cid = inv_tbl->cid; + req->table[i].icd = inv_tbl[i].icd; + req->table[i].cid = inv_tbl[i].cid; req->icd_count++; - inv_tbl++; } sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); diff --git a/drivers/scsi/be