* SCSI command completion.
*/
static inline void
-lpfc_rampup_queue_depth(struct lpfc_hba *phba,
+lpfc_rampup_queue_depth(struct lpfc_vport *vport,
struct scsi_device *sdev)
{
unsigned long flags;
+ struct lpfc_hba *phba = vport->phba;
atomic_inc(&phba->num_cmd_success);
- if (phba->cfg_lun_queue_depth <= sdev->queue_depth)
+ if (vport->cfg_lun_queue_depth <= sdev->queue_depth)
return;
-
spin_lock_irqsave(&phba->hbalock, flags);
if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) {
spin_unlock_irqrestore(&phba->hbalock, flags);
return;
}
-
phba->last_ramp_up_time = jiffies;
spin_unlock_irqrestore(&phba->hbalock, flags);
void
lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
{
- struct lpfc_vport *vport;
- struct Scsi_Host *host;
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
struct scsi_device *sdev;
unsigned long new_queue_depth;
unsigned long num_rsrc_err, num_cmd_success;
+ int i;
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
num_cmd_success = atomic_read(&phba->num_cmd_success);
- spin_lock_irq(&phba->hbalock);
- list_for_each_entry(vport, &phba->port_list, listentry) {
- host = lpfc_shost_from_vport(vport);
- if (!scsi_host_get(host))
- continue;
-
- spin_unlock_irq(&phba->hbalock);
-
- shost_for_each_device(sdev, host) {
- new_queue_depth = sdev->queue_depth * num_rsrc_err /
- (num_rsrc_err + num_cmd_success);
- if (!new_queue_depth)
- new_queue_depth = sdev->queue_depth - 1;
- else
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+ for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ shost_for_each_device(sdev, shost) {
new_queue_depth =
- sdev->queue_depth - new_queue_depth;
-
- if (sdev->ordered_tags)
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
- new_queue_depth);
- else
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
- new_queue_depth);
+ sdev->queue_depth * num_rsrc_err /
+ (num_rsrc_err + num_cmd_success);
+ if (!new_queue_depth)
+ new_queue_depth = sdev->queue_depth - 1;
+ else
+ new_queue_depth = sdev->queue_depth -
+ new_queue_depth;
+ if (sdev->ordered_tags)
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TAG,
+ new_queue_depth);
+ else
+ scsi_adjust_queue_depth(sdev,
+ MSG_SIMPLE_TAG,
+ new_queue_depth);
+ }
}
- spin_lock_irq(&phba->hbalock);
- scsi_host_put(host);
- }
+ lpfc_destroy_vport_work_array(vports);
spin_unlock_irq(&phba->hbalock);
atomic_set(&phba->num_rsrc_err, 0);
atomic_set(&phba->num_cmd_success, 0);
void
lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
{
- struct lpfc_vport *vport;
- struct Scsi_Host *host;
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
struct scsi_device *sdev;
-
- spin_lock_irq(&phba->hbalock);
- list_for_each_entry(vport, &phba->port_list, listentry) {
- host = lpfc_shost_from_vport(vport);
- if (!scsi_host_get(host))
- continue;
-
- spin_unlock_irq(&phba->hbalock);
- shost_for_each_device(sdev, host) {
- if (sdev->ordered_tags)
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
- sdev->queue_depth+1);
- else
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
- sdev->queue_depth+1);
+ int i;
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+ for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ shost_for_each_device(sdev, shost) {
+ if (sdev->ordered_tags)
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TAG,
+ sdev->queue_depth+1);
+ else
+ scsi_adjust_queue_depth(sdev,
+ MSG_SIMPLE_TAG,
+ sdev->queue_depth+1);
+ }
}
- spin_lock_irq(&phba->hbalock);
- scsi_host_put(host);
- }
- spin_unlock_irq(&phba->hbalock);
+ lpfc_destroy_vport_work_array(vports);
atomic_set(&phba->num_rsrc_err, 0);
atomic_set(&phba->num_cmd_success, 0);
}
if (!result)
- lpfc_rampup_queue_depth(phba, sdev);
+ lpfc_rampup_queue_depth(vport, sdev);
if (!result && pnode != NULL &&
((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
- (phba->cfg_lun_queue_depth > sdev->queue_depth)) {
+ (vport->cfg_lun_queue_depth > sdev->queue_depth)) {
shost_for_each_device(tmp_sdev, sdev->host) {
- if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) {
+ if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){
if (tmp_sdev->id != sdev->id)
continue;
if (tmp_sdev->ordered_tags)
schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
if (++loop_count
- > (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
+ > (2 * vport->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
break;
}
loopcnt++;
rdata = cmnd->device->hostdata;
if (!rdata ||
- (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) {
+ (loopcnt > ((vport->cfg_devloss_tmo * 2) + 1))){
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d (%d):0721 LUN Reset rport "
"failure: cnt x%x rdata x%p\n",
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
if (++loopcnt
- > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
+ > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
break;
cnt = lpfc_sli_sum_iocb(phba,
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
if (++loopcnt
- > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
+ > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
break;
cnt = lpfc_sli_sum_iocb(phba,
* extra. This list of scsi bufs exists for the lifetime of the driver.
*/
total = phba->total_scsi_bufs;
- num_to_alloc = phba->cfg_lun_queue_depth + 2;
+ num_to_alloc = vport->cfg_lun_queue_depth + 2;
/* Allow some exchanges to be available always to complete discovery */
if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
if (sdev->tagged_supported)
- scsi_activate_tcq(sdev, phba->cfg_lun_queue_depth);
+ scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
else
- scsi_deactivate_tcq(sdev, phba->cfg_lun_queue_depth);
+ scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
/*
* Initialize the fc transport attributes for the target
* target pointer is stored in the starget_data for the
* driver's sysfs entry point functions.
*/
- rport->dev_loss_tmo = phba->cfg_devloss_tmo;
+ rport->dev_loss_tmo = vport->cfg_devloss_tmo;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring(phba);
.shost_attrs = lpfc_hba_attrs,
.max_sectors = 0xFFFF,
};
+
+struct scsi_host_template lpfc_vport_template = {
+ .module = THIS_MODULE,
+ .name = LPFC_DRIVER_NAME,
+ .info = lpfc_info,
+ .queuecommand = lpfc_queuecommand,
+ .eh_abort_handler = lpfc_abort_handler,
+ .eh_device_reset_handler= lpfc_device_reset_handler,
+ .eh_bus_reset_handler = lpfc_bus_reset_handler,
+ .slave_alloc = lpfc_slave_alloc,
+ .slave_configure = lpfc_slave_configure,
+ .slave_destroy = lpfc_slave_destroy,
+ .scan_finished = lpfc_scan_finished,
+ .this_id = -1,
+ .sg_tablesize = LPFC_SG_SEG_CNT,
+ .cmd_per_lun = LPFC_CMD_PER_LUN,
+ .use_clustering = ENABLE_CLUSTERING,
+ .shost_attrs = lpfc_vport_attrs,
+ .max_sectors = 0xFFFF,
+};