drm/i915: SDVO hotplug have different interrupt status bits for i915/i965/g4x
[linux-2.6.git] / drivers / target / target_core_transport.c
index 4a112b6..69f3f7d 100644 (file)
@@ -1748,7 +1748,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
 
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
-       transport_generic_free_cmd(se_cmd, 0);
 }
 
 /**
@@ -1976,6 +1975,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
        case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
        case TCM_UNKNOWN_MODE_PAGE:
        case TCM_WRITE_PROTECTED:
+       case TCM_ADDRESS_OUT_OF_RANGE:
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
        case TCM_CHECK_CONDITION_NOT_READY:
@@ -2440,7 +2440,7 @@ static void transport_xor_callback(struct se_cmd *cmd)
 
        offset = 0;
        for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
-               addr = kmap_atomic(sg_page(sg), KM_USER0);
+               addr = kmap_atomic(sg_page(sg));
                if (!addr)
                        goto out;
 
@@ -2448,7 +2448,7 @@ static void transport_xor_callback(struct se_cmd *cmd)
                        *(addr + sg->offset + i) ^= *(buf + offset + i);
 
                offset += sg->length;
-               kunmap_atomic(addr, KM_USER0);
+               kunmap_atomic(addr);
        }
 
 out:
@@ -2635,6 +2635,7 @@ static int transport_generic_cmd_sequencer(
                                        cmd, cdb, pr_reg_type) != 0) {
                        cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
                        cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
+                       cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
                        cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
                        return -EBUSY;
                }
@@ -3165,15 +3166,20 @@ static int transport_generic_cmd_sequencer(
                        /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
                        goto out_invalid_cdb_field;
                }
-
+               /*
+                * For the overflow case keep the existing fabric provided
+                * ->data_length.  Otherwise for the underflow case, reset
+                * ->data_length to the smaller SCSI expected data transfer
+                * length.
+                */
                if (size > cmd->data_length) {
                        cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
                        cmd->residual_count = (size - cmd->data_length);
                } else {
                        cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
                        cmd->residual_count = (cmd->data_length - size);
+                       cmd->data_length = size;
                }
-               cmd->data_length = size;
        }
 
        if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB &&
@@ -3673,9 +3679,9 @@ transport_generic_get_mem(struct se_cmd *cmd)
        return 0;
 
 out:
-       while (i >= 0) {
-               __free_page(sg_page(&cmd->t_data_sg[i]));
+       while (i > 0) {
                i--;
+               __free_page(sg_page(&cmd->t_data_sg[i]));
        }
        kfree(cmd->t_data_sg);
        cmd->t_data_sg = NULL;
@@ -4655,6 +4661,15 @@ int transport_send_check_condition_and_sense(
                /* WRITE PROTECTED */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27;
                break;
+       case TCM_ADDRESS_OUT_OF_RANGE:
+               /* CURRENT ERROR */
+               buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
+               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21;
+               break;
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;