diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_target.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 99 |
1 files changed, 84 insertions, 15 deletions
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d3cd271eb127..ac7a7549c669 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -100,7 +100,7 @@ enum fcp_resp_rsp_codes { | |||
100 | */ | 100 | */ |
101 | /* Predefs for callbacks handed to qla2xxx LLD */ | 101 | /* Predefs for callbacks handed to qla2xxx LLD */ |
102 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha, | 102 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha, |
103 | struct atio_from_isp *pkt); | 103 | struct atio_from_isp *pkt, uint8_t); |
104 | static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); | 104 | static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); |
105 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | 105 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, |
106 | int fn, void *iocb, int flags); | 106 | int fn, void *iocb, int flags); |
@@ -230,7 +230,7 @@ static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha) | |||
230 | } | 230 | } |
231 | 231 | ||
232 | static void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, | 232 | static void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, |
233 | struct atio_from_isp *atio) | 233 | struct atio_from_isp *atio, uint8_t ha_locked) |
234 | { | 234 | { |
235 | ql_dbg(ql_dbg_tgt, vha, 0xe072, | 235 | ql_dbg(ql_dbg_tgt, vha, 0xe072, |
236 | "%s: qla_target(%d): type %x ox_id %04x\n", | 236 | "%s: qla_target(%d): type %x ox_id %04x\n", |
@@ -251,7 +251,7 @@ static void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, | |||
251 | atio->u.isp24.fcp_hdr.d_id[2]); | 251 | atio->u.isp24.fcp_hdr.d_id[2]); |
252 | break; | 252 | break; |
253 | } | 253 | } |
254 | qlt_24xx_atio_pkt(host, atio); | 254 | qlt_24xx_atio_pkt(host, atio, ha_locked); |
255 | break; | 255 | break; |
256 | } | 256 | } |
257 | 257 | ||
@@ -274,7 +274,7 @@ static void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, | |||
274 | break; | 274 | break; |
275 | } | 275 | } |
276 | } | 276 | } |
277 | qlt_24xx_atio_pkt(host, atio); | 277 | qlt_24xx_atio_pkt(host, atio, ha_locked); |
278 | break; | 278 | break; |
279 | } | 279 | } |
280 | 280 | ||
@@ -1211,7 +1211,7 @@ void qlt_stop_phase2(struct qla_tgt *tgt) | |||
1211 | 1211 | ||
1212 | mutex_lock(&vha->vha_tgt.tgt_mutex); | 1212 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
1213 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1213 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1214 | while (tgt->irq_cmd_count != 0) { | 1214 | while ((tgt->irq_cmd_count != 0) || (tgt->atio_irq_cmd_count != 0)) { |
1215 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1215 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1216 | udelay(2); | 1216 | udelay(2); |
1217 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1217 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -5350,11 +5350,12 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, | |||
5350 | /* ha->hardware_lock supposed to be held on entry */ | 5350 | /* ha->hardware_lock supposed to be held on entry */ |
5351 | /* called via callback from qla2xxx */ | 5351 | /* called via callback from qla2xxx */ |
5352 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | 5352 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, |
5353 | struct atio_from_isp *atio) | 5353 | struct atio_from_isp *atio, uint8_t ha_locked) |
5354 | { | 5354 | { |
5355 | struct qla_hw_data *ha = vha->hw; | 5355 | struct qla_hw_data *ha = vha->hw; |
5356 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; | 5356 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
5357 | int rc; | 5357 | int rc; |
5358 | unsigned long flags; | ||
5358 | 5359 | ||
5359 | if (unlikely(tgt == NULL)) { | 5360 | if (unlikely(tgt == NULL)) { |
5360 | ql_dbg(ql_dbg_io, vha, 0x3064, | 5361 | ql_dbg(ql_dbg_io, vha, 0x3064, |
@@ -5366,7 +5367,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5366 | * Otherwise, some commands can stuck. | 5367 | * Otherwise, some commands can stuck. |
5367 | */ | 5368 | */ |
5368 | 5369 | ||
5369 | tgt->irq_cmd_count++; | 5370 | tgt->atio_irq_cmd_count++; |
5370 | 5371 | ||
5371 | switch (atio->u.raw.entry_type) { | 5372 | switch (atio->u.raw.entry_type) { |
5372 | case ATIO_TYPE7: | 5373 | case ATIO_TYPE7: |
@@ -5376,7 +5377,11 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5376 | "qla_target(%d): ATIO_TYPE7 " | 5377 | "qla_target(%d): ATIO_TYPE7 " |
5377 | "received with UNKNOWN exchange address, " | 5378 | "received with UNKNOWN exchange address, " |
5378 | "sending QUEUE_FULL\n", vha->vp_idx); | 5379 | "sending QUEUE_FULL\n", vha->vp_idx); |
5380 | if (!ha_locked) | ||
5381 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
5379 | qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL); | 5382 | qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL); |
5383 | if (!ha_locked) | ||
5384 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
5380 | break; | 5385 | break; |
5381 | } | 5386 | } |
5382 | 5387 | ||
@@ -5385,7 +5390,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5385 | if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) { | 5390 | if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) { |
5386 | rc = qlt_chk_qfull_thresh_hold(vha, atio); | 5391 | rc = qlt_chk_qfull_thresh_hold(vha, atio); |
5387 | if (rc != 0) { | 5392 | if (rc != 0) { |
5388 | tgt->irq_cmd_count--; | 5393 | tgt->atio_irq_cmd_count--; |
5389 | return; | 5394 | return; |
5390 | } | 5395 | } |
5391 | rc = qlt_handle_cmd_for_atio(vha, atio); | 5396 | rc = qlt_handle_cmd_for_atio(vha, atio); |
@@ -5394,11 +5399,20 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5394 | } | 5399 | } |
5395 | if (unlikely(rc != 0)) { | 5400 | if (unlikely(rc != 0)) { |
5396 | if (rc == -ESRCH) { | 5401 | if (rc == -ESRCH) { |
5402 | if (!ha_locked) | ||
5403 | spin_lock_irqsave | ||
5404 | (&ha->hardware_lock, flags); | ||
5405 | |||
5397 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ | 5406 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ |
5398 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); | 5407 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); |
5399 | #else | 5408 | #else |
5400 | qlt_send_term_exchange(vha, NULL, atio, 1); | 5409 | qlt_send_term_exchange(vha, NULL, atio, 1); |
5401 | #endif | 5410 | #endif |
5411 | |||
5412 | if (!ha_locked) | ||
5413 | spin_unlock_irqrestore | ||
5414 | (&ha->hardware_lock, flags); | ||
5415 | |||
5402 | } else { | 5416 | } else { |
5403 | if (tgt->tgt_stop) { | 5417 | if (tgt->tgt_stop) { |
5404 | ql_dbg(ql_dbg_tgt, vha, 0xe059, | 5418 | ql_dbg(ql_dbg_tgt, vha, 0xe059, |
@@ -5410,7 +5424,13 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5410 | "qla_target(%d): Unable to send " | 5424 | "qla_target(%d): Unable to send " |
5411 | "command to target, sending BUSY " | 5425 | "command to target, sending BUSY " |
5412 | "status.\n", vha->vp_idx); | 5426 | "status.\n", vha->vp_idx); |
5427 | if (!ha_locked) | ||
5428 | spin_lock_irqsave( | ||
5429 | &ha->hardware_lock, flags); | ||
5413 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); | 5430 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); |
5431 | if (!ha_locked) | ||
5432 | spin_unlock_irqrestore( | ||
5433 | &ha->hardware_lock, flags); | ||
5414 | } | 5434 | } |
5415 | } | 5435 | } |
5416 | } | 5436 | } |
@@ -5427,7 +5447,12 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5427 | break; | 5447 | break; |
5428 | } | 5448 | } |
5429 | ql_dbg(ql_dbg_tgt, vha, 0xe02e, "%s", "IMMED_NOTIFY ATIO"); | 5449 | ql_dbg(ql_dbg_tgt, vha, 0xe02e, "%s", "IMMED_NOTIFY ATIO"); |
5450 | |||
5451 | if (!ha_locked) | ||
5452 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
5430 | qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)atio); | 5453 | qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)atio); |
5454 | if (!ha_locked) | ||
5455 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
5431 | break; | 5456 | break; |
5432 | } | 5457 | } |
5433 | 5458 | ||
@@ -5438,7 +5463,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5438 | break; | 5463 | break; |
5439 | } | 5464 | } |
5440 | 5465 | ||
5441 | tgt->irq_cmd_count--; | 5466 | tgt->atio_irq_cmd_count--; |
5442 | } | 5467 | } |
5443 | 5468 | ||
5444 | /* ha->hardware_lock supposed to be held on entry */ | 5469 | /* ha->hardware_lock supposed to be held on entry */ |
@@ -6384,7 +6409,7 @@ qlt_init_atio_q_entries(struct scsi_qla_host *vha) | |||
6384 | * @ha: SCSI driver HA context | 6409 | * @ha: SCSI driver HA context |
6385 | */ | 6410 | */ |
6386 | void | 6411 | void |
6387 | qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) | 6412 | qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked) |
6388 | { | 6413 | { |
6389 | struct qla_hw_data *ha = vha->hw; | 6414 | struct qla_hw_data *ha = vha->hw; |
6390 | struct atio_from_isp *pkt; | 6415 | struct atio_from_isp *pkt; |
@@ -6397,7 +6422,8 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) | |||
6397 | pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; | 6422 | pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; |
6398 | cnt = pkt->u.raw.entry_count; | 6423 | cnt = pkt->u.raw.entry_count; |
6399 | 6424 | ||
6400 | qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt); | 6425 | qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt, |
6426 | ha_locked); | ||
6401 | 6427 | ||
6402 | for (i = 0; i < cnt; i++) { | 6428 | for (i = 0; i < cnt; i++) { |
6403 | ha->tgt.atio_ring_index++; | 6429 | ha->tgt.atio_ring_index++; |
@@ -6681,16 +6707,59 @@ qla83xx_msix_atio_q(int irq, void *dev_id) | |||
6681 | ha = rsp->hw; | 6707 | ha = rsp->hw; |
6682 | vha = pci_get_drvdata(ha->pdev); | 6708 | vha = pci_get_drvdata(ha->pdev); |
6683 | 6709 | ||
6684 | spin_lock_irqsave(&ha->hardware_lock, flags); | 6710 | spin_lock_irqsave(&ha->tgt.atio_lock, flags); |
6685 | 6711 | ||
6686 | qlt_24xx_process_atio_queue(vha); | 6712 | qlt_24xx_process_atio_queue(vha, 0); |
6687 | qla24xx_process_response_queue(vha, rsp); | ||
6688 | 6713 | ||
6689 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 6714 | spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); |
6690 | 6715 | ||
6691 | return IRQ_HANDLED; | 6716 | return IRQ_HANDLED; |
6692 | } | 6717 | } |
6693 | 6718 | ||
6719 | static void | ||
6720 | qlt_handle_abts_recv_work(struct work_struct *work) | ||
6721 | { | ||
6722 | struct qla_tgt_sess_op *op = container_of(work, | ||
6723 | struct qla_tgt_sess_op, work); | ||
6724 | scsi_qla_host_t *vha = op->vha; | ||
6725 | struct qla_hw_data *ha = vha->hw; | ||
6726 | unsigned long flags; | ||
6727 | |||
6728 | if (qla2x00_reset_active(vha) || (op->chip_reset != ha->chip_reset)) | ||
6729 | return; | ||
6730 | |||
6731 | spin_lock_irqsave(&ha->tgt.atio_lock, flags); | ||
6732 | qlt_24xx_process_atio_queue(vha, 0); | ||
6733 | spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); | ||
6734 | |||
6735 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
6736 | qlt_response_pkt_all_vps(vha, (response_t *)&op->atio); | ||
6737 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
6738 | } | ||
6739 | |||
6740 | void | ||
6741 | qlt_handle_abts_recv(struct scsi_qla_host *vha, response_t *pkt) | ||
6742 | { | ||
6743 | struct qla_tgt_sess_op *op; | ||
6744 | |||
6745 | op = kzalloc(sizeof(*op), GFP_ATOMIC); | ||
6746 | |||
6747 | if (!op) { | ||
6748 | /* do not reach for ATIO queue here. This is best effort err | ||
6749 | * recovery at this point. | ||
6750 | */ | ||
6751 | qlt_response_pkt_all_vps(vha, pkt); | ||
6752 | return; | ||
6753 | } | ||
6754 | |||
6755 | memcpy(&op->atio, pkt, sizeof(*pkt)); | ||
6756 | op->vha = vha; | ||
6757 | op->chip_reset = vha->hw->chip_reset; | ||
6758 | INIT_WORK(&op->work, qlt_handle_abts_recv_work); | ||
6759 | queue_work(qla_tgt_wq, &op->work); | ||
6760 | return; | ||
6761 | } | ||
6762 | |||
6694 | int | 6763 | int |
6695 | qlt_mem_alloc(struct qla_hw_data *ha) | 6764 | qlt_mem_alloc(struct qla_hw_data *ha) |
6696 | { | 6765 | { |