aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/dpt_i2o.c25
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c3
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c8
-rw-r--r--drivers/scsi/iscsi_tcp.c2
-rw-r--r--drivers/scsi/libata-core.c4
-rw-r--r--drivers/scsi/libata-scsi.c12
-rw-r--r--drivers/scsi/megaraid.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c15
-rw-r--r--drivers/scsi/sata_mv.c3
-rw-r--r--drivers/scsi/sata_promise.c12
-rw-r--r--drivers/scsi/sata_sx4.c3
-rw-r--r--drivers/scsi/scsi_error.c7
-rw-r--r--drivers/scsi/scsi_lib.c33
-rw-r--r--drivers/scsi/scsi_scan.c49
-rw-r--r--drivers/scsi/scsi_transport_fc.c59
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c2
-rw-r--r--drivers/scsi/sd.c16
-rw-r--r--drivers/scsi/sr.c20
-rw-r--r--drivers/scsi/st.c19
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c4
23 files changed, 198 insertions, 118 deletions
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 418fc7b896a..6252b9ddc01 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -660,7 +660,12 @@ static int adpt_abort(struct scsi_cmnd * cmd)
msg[2] = 0;
msg[3]= 0;
msg[4] = (u32)cmd;
- if( (rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER)) != 0){
+ if (pHba->host)
+ spin_lock_irq(pHba->host->host_lock);
+ rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
+ if (pHba->host)
+ spin_unlock_irq(pHba->host->host_lock);
+ if (rcode != 0) {
if(rcode == -EOPNOTSUPP ){
printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
return FAILED;
@@ -697,10 +702,15 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
msg[2] = 0;
msg[3] = 0;
+ if (pHba->host)
+ spin_lock_irq(pHba->host->host_lock);
old_state = d->state;
d->state |= DPTI_DEV_RESET;
- if( (rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER)) ){
- d->state = old_state;
+ rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
+ d->state = old_state;
+ if (pHba->host)
+ spin_unlock_irq(pHba->host->host_lock);
+ if (rcode != 0) {
if(rcode == -EOPNOTSUPP ){
printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
return FAILED;
@@ -708,7 +718,6 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
return FAILED;
} else {
- d->state = old_state;
printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
return SUCCESS;
}
@@ -721,6 +730,7 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
{
adpt_hba* pHba;
u32 msg[4];
+ u32 rcode;
pHba = (adpt_hba*)cmd->device->host->hostdata[0];
memset(msg, 0, sizeof(msg));
@@ -729,7 +739,12 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
msg[2] = 0;
msg[3] = 0;
- if(adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER) ){
+ if (pHba->host)
+ spin_lock_irq(pHba->host->host_lock);
+ rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
+ if (pHba->host)
+ spin_unlock_irq(pHba->host->host_lock);
+ if (rcode != 0) {
printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
return FAILED;
} else {
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 8bec0438dc8..5b0edd1f192 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -100,7 +100,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
void ibmvscsi_release_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests);
-void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
void ibmvscsi_handle_crq(struct viosrp_crq *crq,
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index 1045872b017..ce15d9e3962 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -117,9 +117,10 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
*
* no-op for iSeries
*/
-void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
+ return 0;
}
/**
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 8bf5652f106..75db2f5c545 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -230,6 +230,11 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
+ if (rc == H_Resource)
+ /* maybe kexecing and resource is busy. try a reset */
+ rc = ibmvscsi_reset_crq_queue(queue,
+ hostdata);
+
if (rc == 2) {
/* Adapter is good, but other end is not ready */
printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
@@ -281,7 +286,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
* @hostdata: ibmvscsi_host_data of host
*
*/
-void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
int rc;
@@ -309,4 +314,5 @@ void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
printk(KERN_WARNING
"ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
}
+ return rc;
}
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 4fea3e4edaa..3d8009f5534 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -3368,7 +3368,7 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
switch(param) {
case ISCSI_PARAM_MAX_RECV_DLENGTH: {
char *saveptr = conn->data;
- int flags = GFP_KERNEL;
+ gfp_t flags = GFP_KERNEL;
if (conn->data_size >= value) {
conn->max_recv_dlength = value;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 665ae79e1fd..d0a0fdbd0fc 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2443,7 +2443,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
struct scatterlist *psg = &qc->pad_sgent;
void *addr = kmap_atomic(psg->page, KM_IRQ0);
memcpy(addr + psg->offset, pad_buf, qc->pad_len);
- kunmap_atomic(psg->page, KM_IRQ0);
+ kunmap_atomic(addr, KM_IRQ0);
}
} else {
if (sg_dma_len(&sg[0]) > 0)
@@ -2717,7 +2717,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
if (qc->tf.flags & ATA_TFLAG_WRITE) {
void *addr = kmap_atomic(psg->page, KM_IRQ0);
memcpy(pad_buf, addr + psg->offset, qc->pad_len);
- kunmap_atomic(psg->page, KM_IRQ0);
+ kunmap_atomic(addr, KM_IRQ0);
}
sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 379e8708976..2282c04fee4 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2044,7 +2044,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
else {
u8 *scsicmd = cmd->cmnd;
- if (scsicmd[0] == INQUIRY) {
+ if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
u8 *buf = NULL;
unsigned int buflen;
@@ -2058,9 +2058,6 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
* device. 2) Ensure response data format / ATAPI information
* are always correct.
*/
- /* FIXME: do we ever override EVPD pages and the like, with
- * this code?
- */
if (buf[2] == 0) {
buf[2] = 0x5;
buf[3] = 0x32;
@@ -2173,9 +2170,12 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
if (unlikely(!ata_dev_present(dev)))
return NULL;
- if (!atapi_enabled) {
- if (unlikely(dev->class == ATA_DEV_ATAPI))
+ if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) {
+ if (unlikely(dev->class == ATA_DEV_ATAPI)) {
+ printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n",
+ ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled");
return NULL;
+ }
}
return dev;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index f9792528e33..578143e93a6 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -664,7 +664,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
sg->offset;
} else
buf = cmd->request_buffer;
- memset(cmd->request_buffer, 0, cmd->cmnd[4]);
+ memset(buf, 0, cmd->cmnd[4]);
if (cmd->use_sg) {
struct scatterlist *sg;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7096945ea23..7b3efd53129 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2476,17 +2476,9 @@ typedef struct scsi_qla_host {
*/
#define LOOP_TRANSITION(ha) \
(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \
- test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
-
-#define LOOP_NOT_READY(ha) \
- ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \
- test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || \
- test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
- test_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) || \
+ test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
atomic_read(&ha->loop_state) == LOOP_DOWN)
-#define LOOP_RDY(ha) (!LOOP_NOT_READY(ha))
-
#define TGT_Q(ha, t) (ha->otgt[t])
#define to_qla_host(x) ((scsi_qla_host_t *) (x)->hostdata)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 2d720121a0d..c46d2469b85 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1259,7 +1259,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
rval = qla2x00_get_adapter_id(ha,
&loop_id, &al_pa, &area, &domain, &topo);
if (rval != QLA_SUCCESS) {
- if (LOOP_NOT_READY(ha) || atomic_read(&ha->loop_down_timer) ||
+ if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) ||
(rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
__func__, ha->host_no));
@@ -1796,7 +1796,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
}
if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
- if (LOOP_NOT_READY(ha)) {
+ if (LOOP_TRANSITION(ha)) {
rval = QLA_FUNCTION_FAILED;
} else {
rval = qla2x00_configure_fabric(ha);
@@ -2369,7 +2369,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
if (qla2x00_is_reserved_id(ha, loop_id))
continue;
- if (atomic_read(&ha->loop_down_timer) || LOOP_NOT_READY(ha))
+ if (atomic_read(&ha->loop_down_timer) || LOOP_TRANSITION(ha))
break;
if (swl != NULL) {
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 09afc0f06bd..5181d966fec 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -909,6 +909,21 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
resid = resid_len;
cp->resid = resid;
CMD_RESID_LEN(cp) = resid;
+
+ if (!lscsi_status &&
+ ((unsigned)(cp->request_bufflen - resid) <
+ cp->underflow)) {
+ qla_printk(KERN_INFO, ha,
+ "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+ "detected (%x of %x bytes)...returning "
+ "error status.\n", ha->host_no,
+ cp->device->channel, cp->device->id,
+ cp->device->lun, resid,
+ cp->request_bufflen);
+
+ cp->result = DID_ERROR << 16;
+ break;
+ }
}
cp->result = DID_OK << 16 | lscsi_status;
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index ab7432a5778..9321cdf4568 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -86,7 +86,8 @@ enum {
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_NO_ATAPI),
MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
CRQB_FLAG_READ = (1 << 0),
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 8a8e3e3ef0e..2691625f9bc 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -70,6 +70,9 @@ enum {
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
PDC_RESET = (1 << 11), /* HDMA reset */
+
+ PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+ ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI,
};
@@ -162,8 +165,7 @@ static struct ata_port_info pdc_port_info[] = {
/* board_2037x */
{
.sht = &pdc_ata_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -173,8 +175,7 @@ static struct ata_port_info pdc_port_info[] = {
/* board_20319 */
{
.sht = &pdc_ata_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -184,8 +185,7 @@ static struct ata_port_info pdc_port_info[] = {
/* board_20619 */
{
.sht = &pdc_ata_sht,
- .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
- ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index dcc3ad9a9d6..ac7b0d819eb 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -220,7 +220,8 @@ static struct ata_port_info pdc_port_info[] = {
{
.sht = &pdc_sata_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ ATA_FLAG_NO_ATAPI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 18c5d252301..c0ae9e965f6 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -422,10 +422,15 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
**/
static void scsi_eh_done(struct scsi_cmnd *scmd)
{
+ struct completion *eh_action;
+
SCSI_LOG_ERROR_RECOVERY(3,
printk("%s scmd: %p result: %x\n",
__FUNCTION__, scmd, scmd->result));
- complete(scmd->device->host->eh_action);
+
+ eh_action = scmd->device->host->eh_action;
+ if (eh_action)
+ complete(eh_action);
}
/**
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ce9d73a292e..dc249cb970e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1085,6 +1085,26 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
}
+void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries)
+{
+ struct request *req = cmd->request;
+
+ BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
+ memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+ cmd->cmd_len = req->cmd_len;
+ if (!req->data_len)
+ cmd->sc_data_direction = DMA_NONE;
+ else if (rq_data_dir(req) == WRITE)
+ cmd->sc_data_direction = DMA_TO_DEVICE;
+ else
+ cmd->sc_data_direction = DMA_FROM_DEVICE;
+
+ cmd->transfersize = req->data_len;
+ cmd->allowed = retries;
+ cmd->timeout_per_command = req->timeout;
+}
+EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
+
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
struct scsi_device *sdev = q->queuedata;
@@ -1220,18 +1240,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
goto kill;
}
} else {
- memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
- cmd->cmd_len = req->cmd_len;
- if (rq_data_dir(req) == WRITE)
- cmd->sc_data_direction = DMA_TO_DEVICE;
- else if (req->data_len)
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- else
- cmd->sc_data_direction = DMA_NONE;
-
- cmd->transfersize = req->data_len;
- cmd->allowed = 3;
- cmd->timeout_per_command = req->timeout;
+ scsi_setup_blk_pc_cmnd(cmd, 3);
cmd->done = scsi_generic_done;
}
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94e5167f260..4e6709f448e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -400,6 +400,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
return found_target;
}
+struct work_queue_wrapper {
+ struct work_struct work;
+ struct scsi_target *starget;
+};
+
+static void scsi_target_reap_work(void *data) {
+ struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+ struct scsi_target *starget = wqw->starget;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+
+ kfree(wqw);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+ list_del_init(&starget->siblings);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ transport_remove_device(&starget->dev);
+ device_del(&starget->dev);
+ transport_destroy_device(&starget->dev);
+ put_device(&starget->dev);
+ return;
+
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ return;
+}
+
/**
* scsi_target_reap - check to see if target is in use and destroy if not
*
@@ -411,19 +441,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
*/
void scsi_target_reap(struct scsi_target *starget)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- unsigned long flags;
- spin_lock_irqsave(shost->host_lock, flags);
+ struct work_queue_wrapper *wqw =
+ kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
- if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
- list_del_init(&starget->siblings);
- spin_unlock_irqrestore(shost->host_lock, flags);
- device_del(&starget->dev);
- transport_unregister_device(&starget->dev);
- put_device(&starget->dev);
+ if (!wqw) {
+ starget_printk(KERN_ERR, starget,
+ "Failed to allocate memory in scsi_reap_target()\n");
return;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
+
+ INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
+ wqw->starget = starget;
+ schedule_work(&wqw->work);
}
/**
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6cd5931d9a5..2a1a99a2ef5 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -105,6 +105,7 @@ static struct {
{ FC_PORTSTATE_LINKDOWN, "Linkdown" },
{ FC_PORTSTATE_ERROR, "Error" },
{ FC_PORTSTATE_LOOPBACK, "Loopback" },
+ { FC_PORTSTATE_DELETED, "Deleted" },
};
fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
#define FC_PORTSTATE_MAX_NAMELEN 20
@@ -211,6 +212,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
#define FC_MGMTSRVR_PORTID 0x00000a
+static void fc_shost_remove_rports(void *data);
static void fc_timeout_deleted_rport(void *data);
static void fc_scsi_scan_rport(void *data);
static void fc_rport_terminate(struct fc_rport *rport);
@@ -318,6 +320,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host_next_rport_number(shost) = 0;
fc_host_next_target_id(shost) = 0;
+ fc_host_flags(shost) = 0;
+ INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
return 0;
}
@@ -387,6 +391,7 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \
struct fc_internal *i = to_fc_internal(shost->transportt); \
if ((i->f->get_rport_##field) && \
!((rport->port_state == FC_PORTSTATE_BLOCKED) || \
+ (rport->port_state == FC_PORTSTATE_DELETED) || \
(rport->port_state == FC_PORTSTATE_NOTPRESENT))) \
i->f->get_rport_##field(rport); \
return snprintf(buf, sz, format_string, cast rport->field); \
@@ -402,6 +407,7 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
struct Scsi_Host *shost = rport_to_shost(rport); \
struct fc_internal *i = to_fc_internal(shost->transportt); \
if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
+ (rport->port_state == FC_PORTSTATE_DELETED) || \
(rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
return -EBUSY; \
val = simple_strtoul(buf, NULL, 0); \
@@ -519,6 +525,7 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
struct Scsi_Host *shost = rport_to_shost(rport);
struct fc_internal *i = to_fc_internal(shost->transportt);
if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
+ (rport->port_state == FC_PORTSTATE_DELETED) ||
(rport->port_state == FC_PORTSTATE_NOTPRESENT))
return -EBUSY;
val = simple_strtoul(buf, NULL, 0);
@@ -1769,7 +1776,7 @@ fc_timeout_deleted_rport(void *data)
rport->maxframe_size = -1;
rport->supported_classes = FC_COS_UNSPECIFIED;
rport->roles = FC_RPORT_ROLE_UNKNOWN;
- rport->port_state = FC_PORTSTATE_NOTPRESENT;
+ rport->port_state = FC_PORTSTATE_DELETED;
/* remove the identifiers that aren't used in the consisting binding */
switch (fc_host_tgtid_bind_type(shost)) {
@@ -1789,14 +1796,23 @@ fc_timeout_deleted_rport(void *data)
break;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
-
/*
* As this only occurs if the remote port (scsi target)
* went away and didn't come back - we'll remove
* all attached scsi devices.
+ *
+ * We'll schedule the shost work item to perform the actual removal
+ * to avoid recursion in the different flush calls if we perform
+ * the removal in each target - and there are lots of targets
+ * whose timeouts fire at the same time.
*/
- fc_rport_tgt_remove(rport);
+
+ if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
+ fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
+ scsi_queue_work(shost, &fc_host_rport_del_work(shost));
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
/**
@@ -1818,6 +1834,41 @@ fc_scsi_scan_rport(void *data)
}
+/**
+ * fc_shost_remove_rports - called to remove all rports that are marked
+ * as in a deleted (not connected) state.
+ *
+ * @data: shost whose rports are to be looked at
+ **/
+static void
+fc_shost_remove_rports(void *data)
+{
+ struct Scsi_Host *shost = (struct Scsi_Host *)data;
+ struct fc_rport *rport, *next_rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
+
+ fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
+
+restart_search:
+ list_for_each_entry_safe(rport, next_rport,
+ &fc_host_rport_bindings(shost), peers) {
+ if (rport->port_state == FC_PORTSTATE_DELETED) {
+ rport->port_state = FC_PORTSTATE_NOTPRESENT;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ fc_rport_tgt_remove(rport);
+ spin_lock_irqsave(shost->host_lock, flags);
+ goto restart_search;
+ }
+ }
+
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+
MODULE_AUTHOR("Martin Hicks");
MODULE_DESCRIPTION("FC Transport Attributes");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 49fd18c1a9c..e08462d50c9 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -249,7 +249,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
}
static void*
-mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
{
struct mempool_zone *zone = pool_data;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8613a131771..03fcbab3003 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -245,24 +245,10 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
* SG_IO from block layer already setup, just copy cdb basically
*/
if (blk_pc_request(rq)) {
- if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
- return 0;
-
- memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
- SCpnt->cmd_len = rq->cmd_len;
- if (rq_data_dir(rq) == WRITE)
- SCpnt->sc_data_direction = DMA_TO_DEVICE;
- else if (rq->data_len)
- SCpnt->sc_data_direction = DMA_FROM_DEVICE;
- else
- SCpnt->sc_data_direction = DMA_NONE;
-
- this_count = rq->data_len;
+ scsi_setup_blk_pc_cmnd(SCpnt, SD_PASSTHROUGH_RETRIES);
if (rq->timeout)
timeout = rq->timeout;
- SCpnt->transfersize = rq->data_len;
- SCpnt->allowed = SD_PASSTHROUGH_RETRIES;
goto queue;
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index d68cea753bb..fb4012b5c18 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -320,25 +320,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
* these are already setup, just copy cdb basically
*/
if (SCpnt->request->flags & REQ_BLOCK_PC) {
- struct request *rq = SCpnt->request;
+ scsi_setup_blk_pc_cmnd(SCpnt, MAX_RETRIES);
- if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
- return 0;
-
- memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
- SCpnt->cmd_len = rq->cmd_len;
- if (!rq->data_len)
- SCpnt->sc_data_direction = DMA_NONE;
- else if (rq_data_dir(rq) == WRITE)
- SCpnt->sc_data_direction = DMA_TO_DEVICE;
- else
- SCpnt->sc_data_direction = DMA_FROM_DEVICE;
-
- this_count = rq->data_len;
- if (rq->timeout)
- timeout = rq->timeout;
+ if (SCpnt->timeout_per_command)
+ timeout = SCpnt->timeout_per_command;
- SCpnt->transfersize = rq->data_len;
goto queue;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 7ac6ea141ff..dd592f6a252 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4194,27 +4194,10 @@ static void st_intr(struct scsi_cmnd *SCpnt)
*/
static int st_init_command(struct scsi_cmnd *SCpnt)
{
- struct request *rq;
-
if (!(SCpnt->request->flags & REQ_BLOCK_PC))
return 0;
- rq = SCpnt->request;
- if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
- return 0;
-
- memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
- SCpnt->cmd_len = rq->cmd_len;
-
- if (rq_data_dir(rq) == WRITE)
- SCpnt->sc_data_direction = DMA_TO_DEVICE;
- else if (rq->data_len)
- SCpnt->sc_data_direction = DMA_FROM_DEVICE;
- else
- SCpnt->sc_data_direction = DMA_NONE;
-
- SCpnt->timeout_per_command = rq->timeout;
- SCpnt->transfersize = rq->data_len;
+ scsi_setup_blk_pc_cmnd(SCpnt, 0);
SCpnt->done = st_intr;
return 1;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index a7420cad454..1564ca203a3 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -1405,7 +1405,6 @@ static void sym_check_goals(struct sym_hcb *np, struct scsi_target *starget,
goal->iu = 0;
goal->dt = 0;
goal->qas = 0;
- goal->period = 0;
goal->offset = 0;
return;
}
@@ -1465,7 +1464,8 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
* Many devices implement PPR in a buggy way, so only use it if we
* really want to.
*/
- if (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)) {
+ if (goal->offset &&
+ (goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) {
nego = NS_PPR;
} else if (spi_width(starget) != goal->width) {
nego = NS_WIDE;