Commit 5a433f7a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "This is a set of three bug fixes, two of which are regressions from
  recent updates (the 3ware one from 4.1 and the device handler fixes
  from 4.2)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  3w-9xxx: don't unmap bounce buffered commands
  scsi_dh: Use the correct module name when loading device handler
  libiscsi: Fix iscsi_check_transport_timeouts possible infinite loop
parents f24fe98d 15e3d5a2
...@@ -212,6 +212,17 @@ static const struct file_operations twa_fops = { ...@@ -212,6 +212,17 @@ static const struct file_operations twa_fops = {
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
/*
* The controllers use an inline buffer instead of a mapped SGL for small,
* single entry buffers. Note that we treat a zero-length transfer like
* a mapped SGL.
*/
static bool twa_command_mapped(struct scsi_cmnd *cmd)
{
return scsi_sg_count(cmd) != 1 ||
scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
}
/* This function will complete an aen request from the isr */ /* This function will complete an aen request from the isr */
static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id) static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
{ {
...@@ -1339,6 +1350,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) ...@@ -1339,6 +1350,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
} }
/* Now complete the io */ /* Now complete the io */
if (twa_command_mapped(cmd))
scsi_dma_unmap(cmd); scsi_dma_unmap(cmd);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
tw_dev->state[request_id] = TW_S_COMPLETED; tw_dev->state[request_id] = TW_S_COMPLETED;
...@@ -1582,6 +1594,7 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev) ...@@ -1582,6 +1594,7 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
struct scsi_cmnd *cmd = tw_dev->srb[i]; struct scsi_cmnd *cmd = tw_dev->srb[i];
cmd->result = (DID_RESET << 16); cmd->result = (DID_RESET << 16);
if (twa_command_mapped(cmd))
scsi_dma_unmap(cmd); scsi_dma_unmap(cmd);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
} }
...@@ -1765,11 +1778,13 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ ...@@ -1765,11 +1778,13 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
switch (retval) { switch (retval) {
case SCSI_MLQUEUE_HOST_BUSY: case SCSI_MLQUEUE_HOST_BUSY:
if (twa_command_mapped(SCpnt))
scsi_dma_unmap(SCpnt); scsi_dma_unmap(SCpnt);
twa_free_request_id(tw_dev, request_id); twa_free_request_id(tw_dev, request_id);
break; break;
case 1: case 1:
SCpnt->result = (DID_ERROR << 16); SCpnt->result = (DID_ERROR << 16);
if (twa_command_mapped(SCpnt))
scsi_dma_unmap(SCpnt); scsi_dma_unmap(SCpnt);
done(SCpnt); done(SCpnt);
tw_dev->state[request_id] = TW_S_COMPLETED; tw_dev->state[request_id] = TW_S_COMPLETED;
...@@ -1831,8 +1846,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, ...@@ -1831,8 +1846,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
/* Map sglist from scsi layer to cmd packet */ /* Map sglist from scsi layer to cmd packet */
if (scsi_sg_count(srb)) { if (scsi_sg_count(srb)) {
if ((scsi_sg_count(srb) == 1) && if (!twa_command_mapped(srb)) {
(scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
if (srb->sc_data_direction == DMA_TO_DEVICE || if (srb->sc_data_direction == DMA_TO_DEVICE ||
srb->sc_data_direction == DMA_BIDIRECTIONAL) srb->sc_data_direction == DMA_BIDIRECTIONAL)
scsi_sg_copy_to_buffer(srb, scsi_sg_copy_to_buffer(srb,
...@@ -1905,7 +1919,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re ...@@ -1905,7 +1919,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
{ {
struct scsi_cmnd *cmd = tw_dev->srb[request_id]; struct scsi_cmnd *cmd = tw_dev->srb[request_id];
if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH && if (!twa_command_mapped(cmd) &&
(cmd->sc_data_direction == DMA_FROM_DEVICE || (cmd->sc_data_direction == DMA_FROM_DEVICE ||
cmd->sc_data_direction == DMA_BIDIRECTIONAL)) { cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
if (scsi_sg_count(cmd) == 1) { if (scsi_sg_count(cmd) == 1) {
......
...@@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) ...@@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
wake_up(&conn->ehwait); wake_up(&conn->ehwait);
} }
static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
{ {
struct iscsi_nopout hdr; struct iscsi_nopout hdr;
struct iscsi_task *task; struct iscsi_task *task;
if (!rhdr && conn->ping_task) if (!rhdr && conn->ping_task)
return; return -EINVAL;
memset(&hdr, 0, sizeof(struct iscsi_nopout)); memset(&hdr, 0, sizeof(struct iscsi_nopout));
hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
...@@ -996,13 +996,16 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) ...@@ -996,13 +996,16 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
hdr.ttt = RESERVED_ITT; hdr.ttt = RESERVED_ITT;
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
if (!task) if (!task) {
iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
else if (!rhdr) { return -EIO;
} else if (!rhdr) {
/* only track our nops */ /* only track our nops */
conn->ping_task = task; conn->ping_task = task;
conn->last_ping = jiffies; conn->last_ping = jiffies;
} }
return 0;
} }
static int iscsi_nop_out_rsp(struct iscsi_task *task, static int iscsi_nop_out_rsp(struct iscsi_task *task,
...@@ -2092,7 +2095,9 @@ static void iscsi_check_transport_timeouts(unsigned long data) ...@@ -2092,7 +2095,9 @@ static void iscsi_check_transport_timeouts(unsigned long data)
if (time_before_eq(last_recv + recv_timeout, jiffies)) { if (time_before_eq(last_recv + recv_timeout, jiffies)) {
/* send a ping to try to provoke some traffic */ /* send a ping to try to provoke some traffic */
ISCSI_DBG_CONN(conn, "Sending nopout as ping\n"); ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
iscsi_send_nopout(conn, NULL); if (iscsi_send_nopout(conn, NULL))
next_timeout = jiffies + (1 * HZ);
else
next_timeout = conn->last_ping + (conn->ping_timeout * HZ); next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
} else } else
next_timeout = last_recv + recv_timeout; next_timeout = last_recv + recv_timeout;
......
...@@ -111,7 +111,7 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name) ...@@ -111,7 +111,7 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name)
dh = __scsi_dh_lookup(name); dh = __scsi_dh_lookup(name);
if (!dh) { if (!dh) {
request_module(name); request_module("scsi_dh_%s", name);
dh = __scsi_dh_lookup(name); dh = __scsi_dh_lookup(name);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment