[PATCH 7/7] sg_ring: convert core ATA code to sg_ring.

2007-12-18 Thread Rusty Russell
ATA relies so heavily on scsi that it needs to be converted at the
same time.

ATA adds padding to scatterlists in scsi commands, but because there was
no good way of appending to those scatterlists, it had to use boutique
iterators to make sure the padding is included.  With sg_ring, ATA can
simply append an sg_ring entry with the padding, and normal iterators
can be used.

I renamed qc->cursg to qc->cur_sg to catch all the users: they should
now be referring to 'qc->cur_sg[qc->cursg_i]' wherever they were using
'qc->cursg'.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>

diff -r a867138da3e0 drivers/ata/ahci.c
--- a/drivers/ata/ahci.cWed Dec 19 16:48:15 2007 +1100
+++ b/drivers/ata/ahci.cWed Dec 19 17:27:09 2007 +1100
@@ -1479,9 +1479,9 @@ static void ahci_tf_read(struct ata_port
 
 static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
 {
-   struct scatterlist *sg;
struct ahci_sg *ahci_sg;
-   unsigned int n_sg = 0;
+   struct sg_ring *sg;
+   unsigned int i, n_sg = 0;
 
VPRINTK("ENTER\n");
 
@@ -1489,9 +1489,9 @@ static unsigned int ahci_fill_sg(struct 
 * Next, the S/G list.
 */
ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
-   ata_for_each_sg(sg, qc) {
-   dma_addr_t addr = sg_dma_address(sg);
-   u32 sg_len = sg_dma_len(sg);
+   sg_ring_for_each(qc->sg, sg, i) {
+   dma_addr_t addr = sg_dma_address(&sg->sg[i]);
+   u32 sg_len = sg_dma_len(&sg->sg[i]);
 
ahci_sg->addr = cpu_to_le32(addr & 0x);
ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
diff -r a867138da3e0 drivers/ata/libata-core.c
--- a/drivers/ata/libata-core.c Wed Dec 19 16:48:15 2007 +1100
+++ b/drivers/ata/libata-core.c Wed Dec 19 17:27:09 2007 +1100
@@ -1596,8 +1596,8 @@ static void ata_qc_complete_internal(str
  */
 unsigned ata_exec_internal_sg(struct ata_device *dev,
  struct ata_taskfile *tf, const u8 *cdb,
- int dma_dir, struct scatterlist *sgl,
- unsigned int n_elem, unsigned long timeout)
+ int dma_dir, struct sg_ring *sg,
+ unsigned long timeout)
 {
struct ata_link *link = dev->link;
struct ata_port *ap = link->ap;
@@ -1657,7 +1657,7 @@ unsigned ata_exec_internal_sg(struct ata
qc->flags |= ATA_QCFLAG_RESULT_TF;
qc->dma_dir = dma_dir;
if (dma_dir != DMA_NONE)
-   ata_sg_init(qc, sgl, n_elem);
+   ata_sg_init(qc, sg);
 
qc->private_data = &wait;
qc->complete_fn = ata_qc_complete_internal;
@@ -1770,18 +1770,16 @@ unsigned ata_exec_internal(struct ata_de
   int dma_dir, void *buf, unsigned int buflen,
   unsigned long timeout)
 {
-   struct scatterlist *psg = NULL, sg;
-   unsigned int n_elem = 0;
+   struct sg_ring *psg = NULL;
+   DECLARE_SG_RING(sg, 1);
 
if (dma_dir != DMA_NONE) {
WARN_ON(!buf);
-   sg_init_one(&sg, buf, buflen);
-   psg = &sg;
-   n_elem++;
-   }
-
-   return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem,
-   timeout);
+   sg_ring_single(&sg.ring, buf, buflen);
+   psg = &sg.ring;
+   }
+
+   return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, timeout);
 }
 
 /**
@@ -4438,6 +4436,36 @@ static unsigned int ata_dev_init_params(
return err_mask;
 }
 
+static struct sg_ring *sg_ring_prev(struct sg_ring *sg)
+{
+   return list_entry(sg->list.prev, struct sg_ring, list);
+}
+
+/* To be paranoid, we handle empty scatterlist ring entries here. */
+static struct sg_ring *sg_find_end(struct sg_ring *sg, unsigned int *num)
+{
+   struct sg_ring *i;
+
+   for (i = sg_ring_prev(sg); i->num == 0; i = sg_ring_prev(i)) {
+   /* sg_ring must not be entirely empty. */
+   BUG_ON(i == sg);
+   }
+   *num = i->num - 1;
+   return i;
+}
+
+static void add_padding_to_tail(struct sg_ring *sg, unsigned int padding)
+{
+   struct sg_ring *tail = sg_ring_prev(sg);
+
+   /* It's possible that the entire sg element got moved to padding. */
+   if (tail->num == 0) {
+   BUG_ON(tail->max == 0);
+   tail->num++;
+   }
+   tail->sg[tail->num - 1].length += padding;
+}
+
 /**
  * ata_sg_clean - Unmap DMA memory associated with command
  * @qc: Command containing DMA memory to be released
@@ -4450,37 +4478,39 @@ void ata_sg_clean(struct ata_queued_cmd 
 void ata_sg_clean(struct ata_queued_cmd *qc)
 {
struct ata_port *ap = qc->ap;
-   struct scatterlist *sg = qc->__sg;
int dir = qc->dma_dir;
-   void *pad_buf = NULL;
-
-   WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
-   WARN_ON(sg == NULL);
-
-   VP

[PATCH 6/7] sg_ring: libata simplification

2007-12-18 Thread Rusty Russell
[This patch has been obsoleted: Tejun has a more complete one, but
it's not in mainline yet, so this serves to make the next patch
apply].

libata separates the single buffer case from the scatterlist case
internally.  It's not clear that this is necessary.

Remove the ATA_QCFLAG_SINGLE flag, and buf_virt pointer, and always
initialize qc->nbytes in ata_sg_init().

It's possible that the ATA_QCFLAG_SG and ATA_QCFLAG_DMAMAP flags could
be entirely removed, and we could use whether qc->__sg is NULL or not.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>

diff -r 8b1075c7ad47 drivers/ata/libata-core.c
--- a/drivers/ata/libata-core.c Tue Nov 13 21:00:47 2007 +1100
+++ b/drivers/ata/libata-core.c Wed Nov 14 15:31:07 2007 +1100
@@ -1648,16 +1648,8 @@ unsigned ata_exec_internal_sg(struct ata
memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
qc->flags |= ATA_QCFLAG_RESULT_TF;
qc->dma_dir = dma_dir;
-   if (dma_dir != DMA_NONE) {
-   unsigned int i, buflen = 0;
-   struct scatterlist *sg;
-
-   for_each_sg(sgl, sg, n_elem, i)
-   buflen += sg->length;
-
+   if (dma_dir != DMA_NONE)
ata_sg_init(qc, sgl, n_elem);
-   qc->nbytes = buflen;
-   }
 
qc->private_data = &wait;
qc->complete_fn = ata_qc_complete_internal;
@@ -4543,9 +4535,6 @@ void ata_sg_clean(struct ata_queued_cmd 
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
WARN_ON(sg == NULL);
 
-   if (qc->flags & ATA_QCFLAG_SINGLE)
-   WARN_ON(qc->n_elem > 1);
-
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
/* if we padded the buffer out to 32-bit bound, and data
@@ -4566,16 +4555,6 @@ void ata_sg_clean(struct ata_queued_cmd 
memcpy(addr + psg->offset, pad_buf, qc->pad_len);
kunmap_atomic(addr, KM_IRQ0);
}
-   } else {
-   if (qc->n_elem)
-   dma_unmap_single(ap->dev,
-   sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
-   dir);
-   /* restore sg */
-   sg->length += qc->pad_len;
-   if (pad_buf)
-   memcpy(qc->buf_virt + sg->length - qc->pad_len,
-  pad_buf, qc->pad_len);
}
 
qc->flags &= ~ATA_QCFLAG_DMAMAP;
@@ -4807,16 +4786,8 @@ void ata_noop_qc_prep(struct ata_queued_
 
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
-   qc->flags |= ATA_QCFLAG_SINGLE;
-
-   qc->__sg = &qc->sgent;
-   qc->n_elem = 1;
-   qc->orig_n_elem = 1;
-   qc->buf_virt = buf;
-   qc->nbytes = buflen;
-   qc->cursg = qc->__sg;
-
sg_init_one(&qc->sgent, buf, buflen);
+   ata_sg_init(qc, &qc->sgent, 1);
 }
 
 /**
@@ -4841,75 +4813,13 @@ void ata_sg_init(struct ata_queued_cmd *
qc->n_elem = n_elem;
qc->orig_n_elem = n_elem;
qc->cursg = qc->__sg;
-}
-
-/**
- * ata_sg_setup_one - DMA-map the memory buffer associated with a command.
- * @qc: Command with memory buffer to be mapped.
- *
- * DMA-map the memory buffer associated with queued_cmd @qc.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- *
- * RETURNS:
- * Zero on success, negative on error.
- */
-
-static int ata_sg_setup_one(struct ata_queued_cmd *qc)
-{
-   struct ata_port *ap = qc->ap;
-   int dir = qc->dma_dir;
-   struct scatterlist *sg = qc->__sg;
-   dma_addr_t dma_address;
-   int trim_sg = 0;
-
-   /* we must lengthen transfers to end on a 32-bit boundary */
-   qc->pad_len = sg->length & 3;
-   if (qc->pad_len) {
-   void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
-   struct scatterlist *psg = &qc->pad_sgent;
-
-   WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
-
-   memset(pad_buf, 0, ATA_DMA_PAD_SZ);
-
-   if (qc->tf.flags & ATA_TFLAG_WRITE)
-   memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
-  qc->pad_len);
-
-   sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
-   sg_dma_len(psg) = ATA_DMA_PAD_SZ;
-   /* trim sg */
-   sg->length -= qc->pad_len;
-   if (sg->length == 0)
-   trim_sg = 1;
-
-   DPRINTK("padding done, sg->length=%u pad_len=%u\n",
-   sg->length, qc->pad_len);
-   }
-
-   if (trim_sg) {
-   qc->n_elem--;
-   goto skip_map;
-   }
-
-   dma_address = dma_map_single(ap->dev, qc->buf_virt,
-sg->length, dir);
-   if (dma_mapping_error(dma_address)) {
-   /* restore sg */
-   sg->length += qc->pad_len;
-   return -1;
-   }
-
-   sg_dma_address(sg) = dma_address;
-

[PATCH 5/7] sg_ring: Convert core scsi code to sg_ring.

2007-12-18 Thread Rusty Russell
If nothing else, the simplification of this logic shows why I prefer
sg_ring over scatterlist chaining.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>

diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1191,28 +1191,28 @@ cciss_scatter_gather(struct pci_dev *pde
struct scsi_cmnd *cmd)
 {
unsigned int len;
-   struct scatterlist *sg;
+   struct sg_ring *sg;
__u64 addr64;
-   int use_sg, i;
+   int count = 0, i;
 
-   BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
-
-   use_sg = scsi_dma_map(cmd);
-   if (use_sg) {   /* not too many addrs? */
-   scsi_for_each_sg(cmd, sg, use_sg, i) {
-   addr64 = (__u64) sg_dma_address(sg);
-   len  = sg_dma_len(sg);
+   if (scsi_dma_map(cmd) >= 0) {   /* not too many addrs? */
+   sg_ring_for_each(scsi_sgring(cmd), sg, i) {
+   addr64 = (__u64) sg_dma_address(&sg->sg[i]);
+   len  = sg_dma_len(&sg->sg[i]);
cp->SG[i].Addr.lower =
(__u32) (addr64 & (__u64) 0x);
cp->SG[i].Addr.upper =
(__u32) ((addr64 >> 32) & (__u64) 
0x);
cp->SG[i].Len = len;
cp->SG[i].Ext = 0;  // we are not chaining
+   count++;
}
}
 
-   cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
-   cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
+   cp->Header.SGList = (__u8) count;   /* no. SGs contig in this cmd */
+   cp->Header.SGTotal = (__u16) count; /* total sgs in this cmd list */
+
+   BUG_ON(count > MAXSGENTRIES);
return;
 }
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -619,18 +619,17 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd 
ses->data_direction = scmd->sc_data_direction;
ses->bufflen = scmd->request_bufflen;
ses->buffer = scmd->request_buffer;
-   ses->use_sg = scmd->use_sg;
ses->resid = scmd->resid;
ses->result = scmd->result;
 
if (sense_bytes) {
scmd->request_bufflen = min_t(unsigned,
   sizeof(scmd->sense_buffer), sense_bytes);
-   sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
-  scmd->request_bufflen);
-   scmd->request_buffer = &ses->sense_sgl;
+
+   sg_ring_single(&ses->sense_sg.ring, scmd->sense_buffer,
+  scmd->request_bufflen);
+   scmd->request_buffer = &ses->sense_sg;
scmd->sc_data_direction = DMA_FROM_DEVICE;
-   scmd->use_sg = 1;
memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->request_bufflen;
@@ -639,7 +638,6 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd 
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->sc_data_direction = DMA_NONE;
-   scmd->use_sg = 0;
if (cmnd) {
memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
memcpy(scmd->cmnd, cmnd, cmnd_size);
@@ -678,7 +676,6 @@ void scsi_eh_restore_cmnd(struct scsi_cm
scmd->sc_data_direction = ses->data_direction;
scmd->request_bufflen = ses->bufflen;
scmd->request_buffer = ses->buffer;
-   scmd->use_sg = ses->use_sg;
scmd->resid = ses->resid;
scmd->result = ses->result;
 }
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -17,7 +17,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include 
 #include 
@@ -737,21 +737,31 @@ static inline unsigned int scsi_sgtable_
return index;
 }
 
-struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+static void free_sgring(struct sg_ring *sg)
 {
struct scsi_host_sg_pool *sgp;
-   struct scatterlist *sgl, *prev, *ret;
+
+   sgp = scsi_sg_pools + scsi_sgtable_index(sg->max);
+
+   mempool_free(sg, sgp->pool);
+}
+
+struct sg_ring *scsi_alloc_sgring(struct scsi_cmnd *cmd, unsigned int num,
+ gfp_t gfp_mask)
+{
+   struct scsi_host_sg_pool *sgp;
+   struct sg_ring *sg, *ret;
unsigned int index;
int this, left;
 
-   BUG_ON(!cmd->use_sg);
+   BUG_ON(!num);
 
-   left = cmd->use_sg;
-   ret = prev = NULL;
+   left = num;
+   ret = NULL;
do {
this = left;
if (this > SCSI_MAX_SG_SEGMENTS) {
-   

[PATCH 4/7] sg_ring: dma_map_sg_ring() helper

2007-12-18 Thread Rusty Russell
Obvious counterpart to dma_map_sg.  Note that this is arch-independent
code; sg_rings are backwards compatible with simple sg arrays.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>
---
 drivers/base/dma-mapping.c  |   13 +
 include/linux/dma-mapping.h |4 
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 
 /*
  * Managed DMA API
@@ -162,6 +163,59 @@ void dmam_free_noncoherent(struct device
 }
 EXPORT_SYMBOL(dmam_free_noncoherent);
 
+/**
+ * dma_map_sg_ring - Map an entire sg ring
+ * @dev: Device to free noncoherent memory for
+ * @sg: The sg_ring
+ * @direction: DMA_TO_DEVICE, DMA_FROM_DEVICE or DMA_BIDIRECTIONAL.
+ *
+ * This returns -ENOMEM if mapping fails.  It's not clear that telling you
+ * it failed is useful though.
+ */
+int dma_map_sg_ring(struct device *dev, struct sg_ring *sg,
+enum dma_data_direction direction)
+{
+   struct sg_ring *i;
+   unsigned int num;
+
+   for (i = sg; i; i = sg_ring_next(i, sg)) {
+   BUG_ON(i->num > i->max);
+   num = dma_map_sg(dev, i->sg, i->num, direction);
+   if (num == 0 && i->num != 0)
+   goto unmap;
+   }
+   return 0;
+
+unmap:
+   while (sg) {
+   dma_unmap_sg(dev, sg->sg, sg->num, direction);
+   sg = sg_ring_next(sg, i);
+   }
+   return -ENOMEM;
+
+}
+EXPORT_SYMBOL(dma_map_sg_ring);
+
+/**
+ * dma_unmap_sg_ring - Unmap an entire sg ring
+ * @dev: Device to free noncoherent memory for
+ * @sg: The sg_ring
+ * @direction: DMA_TO_DEVICE, DMA_FROM_DEVICE or DMA_BIDIRECTIONAL.
+ *
+ * Call after dma_map_sg_ring() succeeds.
+ */
+void dma_unmap_sg_ring(struct device *dev, struct sg_ring *sg,
+  enum dma_data_direction direction)
+{
+   struct sg_ring *i;
+
+   for (i = sg; i; i = sg_ring_next(i, sg)) {
+   BUG_ON(i->num > i->max);
+   dma_unmap_sg(dev, i->sg, i->num, direction);
+   }
+}
+EXPORT_SYMBOL(dma_unmap_sg_ring);
+
 #ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 
 static void dmam_coherent_decl_release(struct device *dev, void *res)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -87,6 +87,12 @@ dma_mark_declared_memory_occupied(struct
 }
 #endif
 
+struct sg_ring;
+extern int dma_map_sg_ring(struct device *dev, struct sg_ring *sg,
+  enum dma_data_direction direction);
+extern void dma_unmap_sg_ring(struct device *dev, struct sg_ring *sg,
+ enum dma_data_direction direction);
+
 /*
  * Managed DMA API
  */
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/7] sg_ring: blk_rq_map_sg_ring as a counterpart to blk_rq_map_sg.

2007-12-18 Thread Rusty Russell
blk_rq_map_sg_ring as a counterpart to blk_rq_map_sg.

Obvious counterpart to blk_rq_map_sg.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>
---
 block/ll_rw_blk.c  |   55 
 include/linux/blkdev.h |1 +
 2 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * for max sense size
@@ -1364,6 +1365,68 @@ new_segment:
 
 EXPORT_SYMBOL(blk_rq_map_sg);
 
+/**
+ * blk_rq_map_sg_ring - map a request to a scatterlist ring.
+ * @q: the request queue this request applies to.
+ * @rq: the request to map
+ * @sg: the sg_ring to populate.
+ *
+ * There must be enough elements in the sg_ring(s) to map the request.
+ */
+void blk_rq_map_sg_ring(struct request_queue *q, struct request *rq,
+   struct sg_ring *sg)
+{
+   struct bio_vec *bvec, *bvprv;
+   struct req_iterator iter;
+   int i, cluster;
+   struct sg_ring *head = sg;
+   struct scatterlist *sgprv;
+
+   i = 0;
+   cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+
+   /*
+* for each bio in rq
+*/
+   bvprv = NULL;
+   sgprv = NULL;
+   rq_for_each_segment(bvec, rq, iter) {
+   int nbytes = bvec->bv_len;
+
+   if (bvprv && cluster) {
+   if (sgprv->length + nbytes > q->max_segment_size)
+   goto new_segment;
+
+   if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
+   goto new_segment;
+   if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
+   goto new_segment;
+
+   sgprv->length += nbytes;
+   } else {
+new_segment:
+   sg_set_page(sg->sg + i, bvec->bv_page, nbytes,
+   bvec->bv_offset);
+   sgprv = sg->sg + i;
+   if (++i == sg->max) {
+   sg->num = i;
+   sg = sg_ring_next(sg, head);
+   i = 0;
+   }
+   }
+   bvprv = bvec;
+   } /* segments in rq */
+
+   /* If we were still working on an sg_ring, set the number and
+* clear any following sg_rings. */
+   if (sg) {
+   sg->num = i;
+   for (sg = sg_ring_next(sg,head); sg; sg = sg_ring_next(sg,head))
+   sg->num = 0;
+   }
+}
+EXPORT_SYMBOL(blk_rq_map_sg_ring);
+
 /*
  * the standard queue merge functions, can be overridden with device
  * specific ones if so desired
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -777,6 +777,8 @@ extern void blk_ordered_complete_seq(str
 extern void blk_ordered_complete_seq(struct request_queue *, unsigned, int);
 
 extern int blk_rq_map_sg(struct request_queue *, struct request *, struct 
scatterlist *);
+struct sg_ring;
+extern void blk_rq_map_sg_ring(struct request_queue *, struct request *, 
struct sg_ring *);
 extern void blk_dump_rq_flags(struct request *, char *);
 extern void generic_unplug_device(struct request_queue *);
 extern void __generic_unplug_device(struct request_queue *);
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/7] sg_ring: use in virtio.

2007-12-18 Thread Rusty Russell
Using sg_rings, we can join together scatterlists returned by other
subsystems, without needing to allocate an extra element for chaining.
This helps the virtio_blk device which wants to prepend and append
metadata to the request's scatterlist.

As an added bonus, the old virtio layer used to pass a scatterlist
array and two numbers indicating the number of readable and writable
elements respectively; now we can simply hand two sg_rings which is
much clearer (each sg_ring contains its own length).

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>
---
 drivers/block/virtio_blk.c|   33 ---
 drivers/char/virtio_console.c |   13 +++---
 drivers/net/virtio_net.c  |   22 +-
 drivers/virtio/virtio_ring.c  |   90 ++--
 include/linux/virtio.h|   12 ++---
 5 files changed, 99 insertions(+), 71 deletions(-)

diff -r 6fe7cf582293 drivers/block/virtio_blk.c
--- a/drivers/block/virtio_blk.cWed Dec 19 16:06:43 2007 +1100
+++ b/drivers/block/virtio_blk.cWed Dec 19 18:29:58 2007 +1100
@@ -5,8 +5,6 @@
 #include 
 #include 
 #include 
-
-#define VIRTIO_MAX_SG  (3+MAX_PHYS_SEGMENTS)
 
 static unsigned char virtblk_index = 'a';
 struct virtio_blk
@@ -24,8 +22,10 @@ struct virtio_blk
 
mempool_t *pool;
 
-   /* Scatterlist: can be too big for stack. */
-   struct scatterlist sg[VIRTIO_MAX_SG];
+   /* Scatterlist ring: can be too big for stack. */
+   DECLARE_SG_RING(out, 1);
+   DECLARE_SG_RING(in, 1);
+   DECLARE_SG_RING(sg, MAX_PHYS_SEGMENTS);
 };
 
 struct virtblk_req
@@ -70,8 +70,8 @@ static bool do_req(struct request_queue 
 static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
   struct request *req)
 {
-   unsigned long num, out, in;
struct virtblk_req *vbr;
+   struct sg_ring *in;
 
vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
if (!vbr)
@@ -95,23 +95,24 @@ static bool do_req(struct request_queue 
if (blk_barrier_rq(vbr->req))
vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
 
-   /* This init could be done at vblk creation time */
-   sg_init_table(vblk->sg, VIRTIO_MAX_SG);
-   sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
-   num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
-   sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr));
+   sg_ring_single(&vblk->out.ring, &vbr->out_hdr, sizeof(vbr->out_hdr));
+   sg_ring_init(&vblk->sg.ring, ARRAY_SIZE(vblk->sg.sg));
+   vblk->sg.ring.num = blk_rq_map_sg(q, vbr->req, vblk->sg.sg);
+   sg_ring_single(&vblk->in.ring, &vbr->in_hdr, sizeof(vbr->in_hdr));
 
if (rq_data_dir(vbr->req) == WRITE) {
vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
-   out = 1 + num;
-   in = 1;
+   /* Chain write request onto output buffers. */
+   list_add_tail(&vblk->sg.ring.list, &vblk->out.ring.list);
+   in = &vblk->in.ring;
} else {
vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
-   out = 1;
-   in = 1 + num;
+   /* Chain input (status) buffer at end of read buffers. */
+   list_add_tail(&vblk->in.ring.list, &vblk->sg.ring.list);
+   in = &vblk->sg.ring;
}
 
-   if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) {
+   if (vblk->vq->vq_ops->add_buf(vblk->vq, &vblk->out.ring, in, vbr)) {
mempool_free(vbr, vblk->pool);
return false;
}
@@ -128,7 +129,7 @@ static void do_virtblk_request(struct re
 
while ((req = elv_next_request(q)) != NULL) {
vblk = req->rq_disk->private_data;
-   BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg));
+   BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg.sg));
 
/* If this request fails, stop queue and wait for something to
   finish to restart it. */
diff -r 6fe7cf582293 drivers/char/virtio_console.c
--- a/drivers/char/virtio_console.c Wed Dec 19 16:06:43 2007 +1100
+++ b/drivers/char/virtio_console.c Wed Dec 19 18:29:58 2007 +1100
@@ -54,15 +54,15 @@ static struct hv_ops virtio_cons;
  * immediately (lguest's Launcher does). */
 static int put_chars(u32 vtermno, const char *buf, int count)
 {
-   struct scatterlist sg[1];
+   DECLARE_SG_RING(sg, 1);
unsigned int len;
 
/* This is a convenient routine to initialize a single-elem sg list */
-   sg_init_one(sg, buf, count);
+   sg_ring_single(&sg.ring, buf, count);
 
/* add_buf wants a token to identify this buffer: we hand it any
 * non-NULL pointer, since there's only ever one buffer. */
-   if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) {
+   if (out_vq->vq_ops->add_buf(out_vq, &sg.ring, NULL, (void *)1) == 0) {
/* Tell Host to go! */
out_vq->vq_ops->kic

[PATCH 1/7] sg_ring: introduce sg_ring: a ring of scatterlist arrays.

2007-12-18 Thread Rusty Russell
This patch introduces 'struct sg_ring', a layer on top of scatterlist
arrays.  It meshes nicely with routines which expect a simple array of
'struct scatterlist' because it is easy to break down the ring into
its constituent arrays.

The sg_ring header also encodes the maximum number of entries, useful
for routines which populate an sg.  We need never hand around a number
of elements any more.

Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>
---
 include/linux/sg_ring.h |   74 
 1 files changed, 74 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/sgring.h

diff --git a/include/linux/sg_ring.h b/include/linux/sg_ring.h
new file mode 100644
--- /dev/null
+++ b/include/linux/sg_ring.h
@@ -0,0 +1,107 @@
+#ifndef _LINUX_SG_RING_H
+#define _LINUX_SG_RING_H
+#include 
+
+/**
+ * struct sg_ring - a ring of scatterlists
+ * @list: the list_head chaining them together
+ * @num: the number of valid sg entries
+ * @max: the maximum number of sg entries (size of the sg array).
+ * @sg: the array of scatterlist entries.
+ *
+ * This provides a convenient encapsulation of one or more scatter gather
+ * arrays.
+ */
+struct sg_ring
+{
+   struct list_head list;
+   unsigned int num, max;
+   struct scatterlist sg[0];
+};
+
+/* This helper declares an sg ring on the stack or in a struct. */
+#define DECLARE_SG_RING(name, max) \
+   struct {\
+   struct sg_ring ring;\
+   struct scatterlist sg[max]; \
+   } name
+
+/**
+ * sg_ring_init - initialize a scatterlist ring.
+ * @sg: the sg_ring.
+ * @max: the size of the trailing sg array.
+ *
+ * After initialization sg is alone in the ring.
+ */
+static inline void sg_ring_init(struct sg_ring *sg, unsigned int max)
+{
+#ifdef CONFIG_DEBUG_SG
+   unsigned int i;
+   for (i = 0; i < max; i++)
+   sg->sg[i].sg_magic = SG_MAGIC;
+#endif
+   INIT_LIST_HEAD(&sg->list);
+   sg->max = max;
+   /* FIXME: This is to clear the page bits. */
+   sg_init_table(sg->sg, sg->max);
+}
+
+/**
+ * sg_ring_single - initialize a one-element scatterlist ring.
+ * @sg: the sg_ring.
+ * @buf: the pointer to the buffer.
+ * @buflen: the length of the buffer.
+ *
+ * Does sg_ring_init and also sets up first (and only) sg element.
+ */
+static inline void sg_ring_single(struct sg_ring *sg,
+ const void *buf,
+ unsigned int buflen)
+{
+   sg_ring_init(sg, 1);
+   sg->num = 1;
+   sg_init_one(&sg->sg[0], buf, buflen);
+}
+
+/**
+ * sg_ring_next - next array in a scatterlist ring.
+ * @sg: the sg_ring.
+ * @head: the sg_ring head.
+ *
+ * This will return NULL once @sg has looped back around to @head.
+ */
+static inline struct sg_ring *sg_ring_next(struct sg_ring *sg,
+  const struct sg_ring *head)
+{
+   sg = list_first_entry(&sg->list, struct sg_ring, list);
+   if (sg == head)
+   sg = NULL;
+   return sg;
+}
+
+/* Helper for writing for loops */
+static inline struct sg_ring *sg_ring_iter(const struct sg_ring *head,
+  struct sg_ring *sg, unsigned int *i)
+{
+   (*i)++;
+   /* While loop lets us skip any zero-entry sg_ring arrays */
+   while (*i == sg->num) {
+   *i = 0;
+   sg = sg_ring_next(sg, head);
+   if (!sg)
+   break;
+   }
+   return sg;
+}
+
+/**
+ * sg_ring_for_each - iterate through an entire sg_ring ring
+ * @head: the head of the sg_ring.
+ * @sg: the sg_ring iterator.
+ * @i: an (unsigned) integer which refers to sg->sg[i].
+ *
+ * The current scatterlist element is sg->sg[i].
+ */
+#define sg_ring_for_each(head, sg, i) \
+   for (sg = head, i = 0; sg; sg = sg_ring_iter(head, sg, &i))
+#endif /* _LINUX_SG_RING_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/7] sg_ring: a ring of scatterlist arrays

2007-12-18 Thread Rusty Russell
This patch series is the start of my attempt to simplify and make explicit
the chained scatterlist logic.

It's not complete: my SATA box boots and seems happy, but all the other
users of SCSI need to be updated and checked.  But I've gotten far enough
to believe it's worth persuing.

Cheers,
Rusty.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] scsi error: add target reset eh handler

2007-12-18 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

Drivers like qla4xxx and bnx2i (and it looks like some fcp drivers too),
want to be able to send a lun reset in the eh device handler and then a
target reset in some other handler. The old linux-iscsi driver, which did
the host per session like open-iscsi did the target reset in the host reset,
because the scsi command accounting that scsi_error.c does worked out
nicely for software iscsi, but does not work for hardware iscsi well.

This patch adds a eh_target_reset_handler any driver can use to send
a target reset.

The next patch will hook qla4xxx into it, and patches for iscsi_tcp/iser
and bnx2i will follow later when bnx2i is closer to getting merged.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_error.c |  121 ++---
 include/scsi/scsi_eh.h|1 +
 include/scsi/scsi_host.h  |1 +
 3 files changed, 105 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 169bc59..fb1f5bc 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
return rtn;
 }
 
+static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
+{
+   sdev->was_reset = 1;
+   sdev->expecting_cc_ua = 1;
+}
+
+/**
+ * scsi_try_target_reset - Ask host to perform a target reset
+ * @scmd:  SCSI cmd used to send a target reset
+ *
+ * Notes:
+ *There is no timeout for this operation.  if this operation is
+ *unreliable for a given host, then the host itself needs to put a
+ *timer on it, and set the host back to a consistent state prior to
+ *returning.
+ */
+static int scsi_try_target_reset(struct scsi_cmnd *scmd)
+{
+   unsigned long flags;
+   int rtn;
+
+   if (!scmd->device->host->hostt->eh_target_reset_handler)
+   return FAILED;
+
+   rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+   if (rtn == SUCCESS) {
+   spin_lock_irqsave(scmd->device->host->host_lock, flags);
+   __starget_for_each_device(scsi_target(scmd->device), NULL,
+ __scsi_report_device_reset);
+   spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+   }
+
+   return rtn;
+}
+
 /**
  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
  * @scmd:  SCSI cmd used to send BDR
@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd 
*scmd)
return FAILED;
 
rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-   if (rtn == SUCCESS) {
-   scmd->device->was_reset = 1;
-   scmd->device->expecting_cc_ua = 1;
-   }
-
+   if (rtn == SUCCESS)
+   __scsi_report_device_reset(scmd->device, NULL);
return rtn;
 }
 
@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
if (scsi_try_bus_device_reset(scmd) != SUCCESS)
-   if (scsi_try_bus_reset(scmd) != SUCCESS)
-   scsi_try_host_reset(scmd);
+   if (scsi_try_target_reset(scmd) != SUCCESS)
+   if (scsi_try_bus_reset(scmd) != SUCCESS)
+   scsi_try_host_reset(scmd);
 }
 
 /**
@@ -1064,6 +1097,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host 
*shost,
 }
 
 /**
+ * scsi_eh_target_reset - send target reset if needed
+ * @shost: scsi host being recovered.
+ * @work_q: &list_head for pending commands.
+ * @done_q:&list_head for processed commands.
+ *
+ * Notes:
+ *Try a target reset.
+ */
+static int scsi_eh_target_reset(struct Scsi_Host *shost,
+   struct list_head *work_q,
+   struct list_head *done_q)
+{
+   struct scsi_cmnd *scmd, *tgtr_scmd, *next;
+   unsigned int id;
+   int rtn;
+
+   for (id = 0; id <= shost->max_id; id++) {
+   tgtr_scmd = NULL;
+   list_for_each_entry(scmd, work_q, eh_entry) {
+   if (id == scmd_id(scmd)) {
+   tgtr_scmd = scmd;
+   break;
+   }
+   }
+   if (!tgtr_scmd)
+   continue;
+
+   SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
+ "to target %d\n",
+ current->comm, id));
+   rtn = scsi_try_target_reset(tgtr_scmd);
+   if (rtn == SUCCESS) {
+   list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
+   if (id == scmd_id(scmd))
+   if (!scsi_de

[PATCH 2/2] qla4xxx: Add target reset functionality

2007-12-18 Thread michaelc
From: Mike Christie <[EMAIL PROTECTED]>

This patch adds target reset functionalty.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/qla4xxx/ql4_fw.h   |1 +
 drivers/scsi/qla4xxx/ql4_glbl.h |2 +
 drivers/scsi/qla4xxx/ql4_mbx.c  |   39 
 drivers/scsi/qla4xxx/ql4_os.c   |   74 ++-
 4 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index fe415ec..ed8ee66 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -216,6 +216,7 @@ union external_hw_config_reg {
 #define MBOX_CMD_ABOUT_FW  0x0009
 #define MBOX_CMD_PING  0x000B
 #define MBOX_CMD_LUN_RESET 0x0016
+#define MBOX_CMD_TARGET_WARM_RESET 0x0017
 #define MBOX_CMD_GET_MANAGEMENT_DATA   0x001E
 #define MBOX_CMD_GET_FW_STATUS 0x001F
 #define MBOX_CMD_SET_ISNS_SERVICE  0x0021
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index a3608e0..b403a17 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
   struct ddb_entry * ddb_entry);
 int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
  int lun);
+int qla4xxx_reset_target(struct scsi_qla_host * ha,
+struct ddb_entry * ddb_entry);
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
  uint32_t offset, uint32_t len);
 int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 35cd73c..c577d79 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct 
ddb_entry * ddb_entry,
return status;
 }
 
+/**
+ * qla4xxx_reset_target - issues target Reset
+ * @ha: Pointer to host adapter structure.
+ * @db_entry: Pointer to device database entry
+ * @un_entry: Pointer to lun entry structure
+ *
+ * This routine performs a TARGET RESET on the specified target.
+ * The caller must ensure that the ddb_entry pointers
+ * are valid before calling this routine.
+ **/
+int qla4xxx_reset_target(struct scsi_qla_host *ha,
+struct ddb_entry *ddb_entry)
+{
+   uint32_t mbox_cmd[MBOX_REG_COUNT];
+   uint32_t mbox_sts[MBOX_REG_COUNT];
+   int status = QLA_SUCCESS;
+
+   DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
+ ddb_entry->os_target_id));
+
+   /*
+* Send target reset command to ISP, so that the ISP will return all
+* outstanding requests with RESET status
+*/
+   memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+   memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+   mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
+   mbox_cmd[1] = ddb_entry->fw_ddb_index;
+   mbox_cmd[5] = 0x01; /* Immediate Command Enable */
+
+   qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+   &mbox_sts[0]);
+   if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
+   mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
+   status = QLA_ERROR;
+
+   return status;
+}
 
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
  uint32_t offset, uint32_t len)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f55b9f7..05e6991 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -73,6 +73,7 @@ static void qla4xxx_recovery_timedout(struct 
iscsi_cls_session *session);
 static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
void (*done) (struct scsi_cmnd *));
 static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
+static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_slave_alloc(struct scsi_device *device);
 static int qla4xxx_slave_configure(struct scsi_device *device);
@@ -85,6 +86,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
.queuecommand   = qla4xxx_queuecommand,
 
.eh_device_reset_handler = qla4xxx_eh_device_reset,
+   .eh_target_reset_handler = qla4xxx_eh_target_reset,
.eh_host_reset_handler  = qla4xxx_eh_host_reset,
 
.slave_configure= qla4xxx_slave_configure,
@@ -1506,7 +1508,7 @@ static int qla4xxx_wait_for_hba_online(struct 
scsi_qla_host *ha)
 }
 
 /**
- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
+ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
  * @ha: pointer to to HBA
  * @t: target id
  * @l: lun id
@@ -1514,20 +1516,

RFC: add target reset handler to scsi_error.c

2007-12-18 Thread michaelc
These patches add a target reset handler to scsi_error.c's error
handler. It is needed because drivers like qla4xxx either have to
do a target reset in the eh_device_reset_handler then do some
tricks so that when that handler is called again we do not send
extra resets, or the driver has to do its own loop in the bus
or host reset handler that loops over the host's targets and sends a
target reset for each target.

Patches were made over scsi-misc.


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: 2.6.24-rc5: tape drive not responding

2007-12-18 Thread Kai Makisara
On Mon, 17 Dec 2007, James Bottomley wrote:

> 
> On Mon, 2007-12-17 at 13:43 -0800, Andrew Morton wrote:
> > On Mon, 17 Dec 2007 16:02:02 -0500
> > "John Stoffel" <[EMAIL PROTECTED]> wrote:
> > 
> > > 
> > > Just to confirm, the propsed patch to st.c fixes the issue with
> > > 2.6.24-rc5 as well at 2.6.24-rc5-mm1 with access to my DLT tape
> > > drives.
> > 
> > err, what patch to st.c?
> 
> That's this one:
> 
> http://git.kernel.org/?p=linux/kernel/git/jejb/scsi-misc-2.6.git;a=commit;h=acdd0b1c371b2fbb4b6110a51ba69cb0af9e6f45
> 
I have done some tests. Firstly, I did not see the BUG with 2.6.24-rc5. 
Looking at include/linux/scatterlist.h suggested that CONFIG_DEBUG_SG has 
something to do with this. When enabled SG debugging, I also saw the BUG. 
Adding this patch solved the problem.

You can add

Acked-by: Kai Makisara <[EMAIL PROTECTED]>

if you want. This fix should be included in 2.6.24.

-- 
Kai
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] MAINTAINERS: remove Adam Fritzler, update his email address in other sources

2007-12-18 Thread Joe Perches
On Tue, 2007-12-18 at 06:43 -0700, Matthew Wilcox wrote:
> On Mon, Dec 17, 2007 at 08:48:03PM -0800, Joe Perches wrote:
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 9507b42..690f172 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -3758,13 +3758,6 @@ W:   
> > http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/
> >  T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git
> >  S: Maintained
> >  
> > -TMS380 TOKEN-RING NETWORK DRIVER
> > -P: Adam Fritzler
> > -M: [EMAIL PROTECTED]
> > -L: [EMAIL PROTECTED]
> > -W: http://www.auk.cx/tms380tr/
> > -S: Maintained
> 
> That's pretty unfriendly.  Presumably the linux-tr list is still active
> and would still help people with that driver.  So how about:

The linux-tr list is at least broken, more likely dead.
Subscribe requests to [EMAIL PROTECTED] bounce.

from: http://www.linuxtr.net/index.html

There is a known problem with the mailing list at the moment. If you
have a query you can contact me directly at [EMAIL PROTECTED]



-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] MAINTAINERS: remove Adam Fritzler, update his email address in other sources

2007-12-18 Thread Arjan van de Ven
On Mon, 17 Dec 2007 20:28:00 -0800
Andrew Morton <[EMAIL PROTECTED]> wrote:
> 
> 
> btw, I cheerfully skipped all your spelling-fixes patches.  Some will
> have stuck via subsystem maintainers but I have a secret "no spelling
> fixes unless they're end-user-visible" policy.  That means I'll take
> spelling fixes only if they're in printks or in Documentation/*.
> This is a little defense mechanism to avoid getting buried in
> micropatches.
> 

for something more productive.. add an aspell/ispell hook to checkpatch.pl ;-)



-- 
If you want to reach me at my work email, use [EMAIL PROTECTED]
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH] drivers/scsi/: Spelling fixes

2007-12-18 Thread Salyzyn, Mark
ACK ips line change.

Sincerely -- Mark Salyzyn

> -Original Message-
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of Joe Perches
> Sent: Monday, December 17, 2007 2:40 PM
> To: [EMAIL PROTECTED]
> Cc: Andrew Morton; AACRAID; Andrew Vasquez; Brian King; 
> IpsLinux; Hannes Reinecke; James E.J. Bottomley; James Smart; 
> Mike Christie; Neela Syam Kolli; linux-scsi@vger.kernel.org; 
> [EMAIL PROTECTED]
> Subject: [PATCH] drivers/scsi/: Spelling fixes
> 
> Signed-off-by: Joe Perches <[EMAIL PROTECTED]>
> ---
. . .
>  drivers/scsi/ips.c|2 +-
. . .
> diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
> index 5c5a9b2..901e14b 100644
> --- a/drivers/scsi/ips.c
> +++ b/drivers/scsi/ips.c
> @@ -1313,7 +1313,7 @@ ips_intr_copperhead(ips_ha_t * ha)
>   cstatus.value = (*ha->func.statupd) (ha);
>  
>   if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
> - /* Spurious Interupt ? */
> + /* Spurious Interrupt ? */
>   continue;
>   }
>  
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] scsi: varlen extended and vendor-specific cdbs

2007-12-18 Thread Boaz Harrosh

  Add support for variable-length, extended, and vendor specific
  CDBs to scsi-ml. It is now possible for initiators and ULD's
  to issue these types of commands. LLDs need not change much.
  All they need is to raise the .max_cmd_len to the longest command
  they support (see iscsi patches).

  - clean-up some code paths that did not expect commands to be
larger than 16, and change cmd_len members' type to short as
char is not enough.
  - Add support for varlen_cdb in scsi_execute.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
Signed-off-by: Benny Halevy <[EMAIL PROTECTED]>
---
 block/scsi_ioctl.c   |4 ++--
 drivers/scsi/constants.c |   10 +++---
 drivers/scsi/scsi.c  |   22 +++---
 drivers/scsi/scsi_lib.c  |   27 ++-
 include/scsi/scsi.h  |   40 +---
 include/scsi/scsi_cmnd.h |2 +-
 include/scsi/scsi_host.h |8 +++-
 7 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 91c7322..f08e196 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,13 @@
 #include 
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
6, 10, 10, 12,
16, 12, 10, 10
 };
 
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include 
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int 
cdb_len)
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
-   len = cdbp[7] + 8;
+   len = scsi_varlen_cdb_length(cdbp);
if (len < 10) {
printk("short variable length command, "
   "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int 
cdb_len)
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
-   len = cdbp[7] + 8;
+   len = scsi_varlen_cdb_length(cdbp);
if (len < 10) {
printk("short opcode=0x%x command, len=%d "
   "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
int k, len;
 
print_opcode_name(cdb, 0);
-   if (VARIABLE_LENGTH_CMD == cdb[0])
-   len = cdb[7] + 8;
-   else
-   len = COMMAND_SIZE(cdb[0]);
+   len = scsi_command_size(cdb);
/* print out all bytes in cdb */
for (k = 0; k < len; ++k) 
printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index a0fd785..5846bb6 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)  (cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-   COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -480,6 +471,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
unsigned long flags = 0;
unsigned long timeout;
int rtn = 0;
+   unsigned cmd_len;
 
/* check if the device is still usable */
if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -561,9 +553,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 * Before we queue this command, check if the command
 * length exceeds what the host adapter can handle.
 */
-   if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+   cmd_len = cmd->cmd_len;
+   if (!cmd_len) {
+   BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+   cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+   }
+
+   if (cmd_len > cmd->device->host->max_cmd_len) {
SCSI_LOG_MLQUEUE(3,
-   printk("queuecommand : command too long.\n"));
+   printk("queuecommand : command too long. "
+  "cdb_size=%d host->max_cmd_len=%d\n",
+  cmd->cmd_len, cmd->device->host->max_cmd_len));
cmd->result = (DID_

Re: [PATCH] MAINTAINERS: remove Adam Fritzler, update his email address in other sources

2007-12-18 Thread Matthew Wilcox
On Mon, Dec 17, 2007 at 08:48:03PM -0800, Joe Perches wrote:
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9507b42..690f172 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3758,13 +3758,6 @@ W: 
> http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/
>  T:   git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git
>  S:   Maintained
>  
> -TMS380 TOKEN-RING NETWORK DRIVER
> -P:   Adam Fritzler
> -M:   [EMAIL PROTECTED]
> -L:   [EMAIL PROTECTED]
> -W:   http://www.auk.cx/tms380tr/
> -S:   Maintained

That's pretty unfriendly.  Presumably the linux-tr list is still active
and would still help people with that driver.  So how about:

 TMS380 TOKEN-RING NETWORK DRIVER
-P:   Adam Fritzler
-M:   [EMAIL PROTECTED]
 L:   [EMAIL PROTECTED]
?W:?
-S:   Maintained
+S:   Orphan

(Dunno what to do about W:)

-- 
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] block layer varlen-cdb

2007-12-18 Thread Boaz Harrosh

  - add varlen_cdb and varlen_cdb_len to hold a large user cdb
if needed. They start as empty. Allocation of buffer must
be done by user and held until request execution is done.
  - Since there can be either a fix_length command up to 16 bytes
or a variable_length, larger then 16 bytes, commands but never
both, we hold the two types in a union to save space. The
presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
mode.
  - Please use added rq_{set,get}_varlen_cdb() to set every thing
up in a way that will not confuse drivers that do not support
varlen_cdb's.
  - Note that this patch does not add any size to struct request
since the unsigned cmd_len is split here to 2 ushorts, which
is more then enough.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
---
 block/ll_rw_blk.c  |2 ++
 include/linux/blkdev.h |   27 +--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 8b91994..e80179b 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -261,6 +261,8 @@ static void rq_init(struct request_queue *q, struct request 
*rq)
rq->end_io_data = NULL;
rq->completion_data = NULL;
rq->next_rq = NULL;
+   rq->varlen_cdb_len = 0;
+   rq->varlen_cdb = NULL;
 }
 
 /**
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d18ee67..aa3090c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -287,8 +287,15 @@ struct request {
/*
 * when request is used as a packet command carrier
 */
-   unsigned int cmd_len;
-   unsigned char cmd[BLK_MAX_CDB];
+   unsigned short cmd_len;
+   unsigned short varlen_cdb_len;  /* length of varlen_cdb buffer */
+   union {
+   unsigned char cmd[BLK_MAX_CDB];
+   unsigned char *varlen_cdb;/* an optional variable-length cdb.
+  * points to a user buffer that must
+  * be valid until end of request
+  */
+   };
 
unsigned int data_len;
unsigned int sense_len;
@@ -550,6 +557,22 @@ enum {
 #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & 
REQ_RW_SYNC)
 #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META)
 
+static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short 
cdb_len)
+{
+   rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
+   rq->varlen_cdb_len = cdb_len;
+   rq->varlen_cdb = cdb;
+}
+
+/* If ! a varlen_cdb than return NULL */
+static inline u8 *rq_get_varlen_cdb(struct request *rq)
+{
+   if (!rq->cmd_len && rq->varlen_cdb_len)
+   return rq->varlen_cdb;
+   else
+   return NULL;
+}
+
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
if (rw == READ)
-- 
1.5.3.3


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer

2007-12-18 Thread Boaz Harrosh

  - struct scsi_cmnd had a 16 bytes command buffer of its own.
This is an unnecessary duplication and copy of request's
cmd. It is probably leftovers from the time that scsi_cmnd
could function without a request attached. So clean that up.

  - Once above is done, few places, apart from scsi-ml, needed
adjustments due to changing the data type of scsi_cmnd->cmnd.

  - Lots of drivers still use MAX_COMMAND_SIZE. So I have left
that #define but equate it to BLK_MAX_CDB. The way I see it
and is reflected in the patch below is.
MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
   as per the SCSI standard and is not related
   to the implementation.
BLK_MAX_CDB. - The allocated space at the request level

(*)fixed-length here means commands that their size can be determined
   by their opcode and the CDB does not carry a length specifier, like
   the VARIABLE_LENGTH_CMD(0x7f) command. This is actually not exactly
   true and the SCSI standard also defines extended commands and
   vendor specific commands that can be bigger than 16 bytes. The kernel
   will support these using the same infrastructure used for VARLEN CDB's.
   So in effect MAX_COMMAND_SIZE means the maximum size command
   scsi-ml supports without specifying a cmd_len by ULD's

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
---
 drivers/firewire/fw-sbp2.c   |2 +-
 drivers/s390/scsi/zfcp_dbf.c |2 +-
 drivers/s390/scsi/zfcp_fsf.c |2 +-
 drivers/scsi/53c700.c|6 +++---
 drivers/scsi/a100u2w.c   |2 +-
 drivers/scsi/hptiop.c|6 +++---
 drivers/scsi/ibmvscsi/ibmvscsi.c |2 +-
 drivers/scsi/initio.c|2 +-
 drivers/scsi/scsi_error.c|   14 --
 drivers/scsi/scsi_lib.c  |5 +++--
 drivers/scsi/scsi_tgt_lib.c  |2 ++
 drivers/usb/storage/isd200.c |2 ++
 include/scsi/scsi_cmnd.h |9 +++--
 include/scsi/scsi_eh.h   |4 ++--
 14 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 624ff3e..06b4306 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1215,7 +1215,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, 
scsi_done_fn_t done)
 
memset(orb->request.command_block,
   0, sizeof(orb->request.command_block));
-   memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+   memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
 
orb->base.callback = complete_command_orb;
orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 701046c..7a7f619 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -724,7 +724,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char 
*tag2, int level,
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
-   memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+   memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ff866eb..e9ead12 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4220,7 +4220,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct 
zfcp_fsf_req *fsf_req)
ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
   scpnt->result);
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (void *) &scpnt->cmnd, scpnt->cmd_len);
+ scpnt->cmnd, scpnt->cmd_len);
 
ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
   fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 71ff3fb..85460f8 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
(struct NCR_700_command_slot *)SCp->host_scribble;

dma_unmap_single(hostdata->dev, slot->pCmd,
-sizeof(SCp->cmnd), DMA_TO_DEVICE);
+MAX_COMMAND_SIZE, DMA_TO_DEVICE);
if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
 #ifdef NCR_700_DEBUG
@@ -1003,7 +1003,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct 
s

[PATCHSET 0/3] varlen extended and vendor-specific cdbs

2007-12-18 Thread Boaz Harrosh
Submitted is a patchset for adding support for variable-length, extended, and 
vendor specific CDBs. It should now cover the entire range of the
SCSI standard.

They are based on scsi-misc + the submitted bidi patches.

Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 2 accessors to hide the mess. I think this approach
should be safe. I can easily go back to the separate pointer,
but I figured a little hack is better then a bloat.

This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs

So over all, this cleans things up, and add fixtures with out
any extra cost.

[1/4] Let scsi_cmnd->cmnd use request->cmd buffer
  Here I let scsi_cmnd->cmnd point to the space allocated by
  request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
  is guaranteed to contain the right length of the command.
  I have tried to go over every single place in the kernel that uses
  scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
  that was not at all bad. I hope I did not miss anything.

  I've tested on an x86_64 machine booting from a sata disk and
  ran the iscsi regression tests as well as my bidi and varlen tests
  on top of the complete patchset and all tests passed.

[2/4] block layer varlen-cd
   Here I added an option to use a user supplied buffer for an arbitrary
   large command. Buffer must be kept valid until execution of request
   ends. The pointer to the buffer shares it's space with the fixed
   length command, so the size of struct request does not change.

[3/4] scsi: varlen extended and vendor-specific cdbs
  Adds support for variable length, extended, and vendor-specific
  cdbs at the scsi mid-layer.

I will send a patch to iscsi once the pending iscsi patchset gets
committed into scsi-misc.

Boaz


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: In which case EWOULDBLOCK is set while a write operation

2007-12-18 Thread Mulyadi Santosa
Hi..

> In which case EWOULDBLOCK / EAGAIN is set while a write operation ?

i think it will happen if you use O_NONBLOCK but writing operation
itself will clearly block (for numerous reasons e.g block needs to be
allocated first and so on).

> Can any one give detailed processing of a write operation for a file system
> with journaling , like EXT3 File System.

better grab book like Understanding the Linux kernel 3rd edition or
Linux Device Driver 3rd edition. It is explained quite extensively
there.

regards,

Mulyadi.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] MAINTAINERS: zfcp

2007-12-18 Thread Swen Schillig
James

we are planning a major rewrite of the zfcp driver, 
meaning that a lot of patches will hit the mailing-list in the near future.

Since I can't support this additional work-load along with my other 
responsibilities we are shifting the maintainership to
Christof Schmitt as the maintainer and
Martin Peschke as the co-maintainer.

Please support the two in providing us a new and more stable
zfcp environment.

Thanks
Swen

---
 MAINTAINERS |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

Index: scsi-misc/MAINTAINERS
===
--- scsi-misc.orig/MAINTAINERS
+++ scsi-misc/MAINTAINERS
@@ -3246,8 +3246,10 @@ W:   http://www.ibm.com/developerworks/lin
 S: Supported
 
 S390 ZFCP DRIVER
-P: Swen Schillig
-M: [EMAIL PROTECTED]
+P: Christof Schmitt
+M: [EMAIL PROTECTED]
+P: Martin Peschke
+M: [EMAIL PROTECTED]
 M: [EMAIL PROTECTED]
 L: [EMAIL PROTECTED]
 W: http://www.ibm.com/developerworks/linux/linux390/
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] blktrace: Add blktrace ioctls to SCSI generic devices

2007-12-18 Thread Christof Schmitt
Since the SCSI layer uses the request queues from the block layer,
blktrace can also be used to trace the requests to all SCSI devices
(like SCSI tape drives), not only disks. The only missing part is the
ioctl interface to start and stop tracing.

This patch adds the SETUP, START, STOP and TEARDOWN ioctls from
blktrace to the sg device files. With this change, blktrace can be
used for SCSI devices like for disks, e.g.:
blktrace -d /dev/sg1 -o - | blkparse -i -

Signed-off-by: Christof Schmitt <[EMAIL PROTECTED]>
---
 block/blktrace.c |   24 ++--
 block/compat_ioctl.c |5 -
 drivers/scsi/sg.c|   12 
 include/linux/blktrace_api.h |   12 ++--
 4 files changed, 40 insertions(+), 13 deletions(-)

--- a/block/blktrace.c  2007-12-17 21:51:45.0 +0100
+++ b/block/blktrace.c  2007-12-17 21:51:45.0 +0100
@@ -236,7 +236,7 @@ static void blk_trace_cleanup(struct blk
kfree(bt);
 }
 
-static int blk_trace_remove(struct request_queue *q)
+int blk_trace_remove(struct request_queue *q)
 {
struct blk_trace *bt;
 
@@ -250,6 +250,7 @@ static int blk_trace_remove(struct reque
 
return 0;
 }
+EXPORT_SYMBOL_GPL(blk_trace_remove);
 
 static int blk_dropped_open(struct inode *inode, struct file *filp)
 {
@@ -317,18 +318,17 @@ static struct rchan_callbacks blk_relay_
 /*
  * Setup everything required to start tracing
  */
-int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
+int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct blk_user_trace_setup *buts)
 {
struct blk_trace *old_bt, *bt = NULL;
struct dentry *dir = NULL;
-   char b[BDEVNAME_SIZE];
int ret, i;
 
if (!buts->buf_size || !buts->buf_nr)
return -EINVAL;
 
-   strcpy(buts->name, bdevname(bdev, b));
+   strcpy(buts->name, name);
 
/*
 * some device names have larger paths - convert the slashes
@@ -353,7 +353,7 @@ int do_blk_trace_setup(struct request_qu
goto err;
 
bt->dir = dir;
-   bt->dev = bdev->bd_dev;
+   bt->dev = dev;
atomic_set(&bt->dropped, 0);
 
ret = -EIO;
@@ -400,8 +400,8 @@ err:
return ret;
 }
 
-static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
-  char __user *arg)
+int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+   char __user *arg)
 {
struct blk_user_trace_setup buts;
int ret;
@@ -410,7 +410,7 @@ static int blk_trace_setup(struct reques
if (ret)
return -EFAULT;
 
-   ret = do_blk_trace_setup(q, bdev, &buts);
+   ret = do_blk_trace_setup(q, name, dev, &buts);
if (ret)
return ret;
 
@@ -419,8 +419,9 @@ static int blk_trace_setup(struct reques
 
return 0;
 }
+EXPORT_SYMBOL_GPL(blk_trace_setup);
 
-static int blk_trace_startstop(struct request_queue *q, int start)
+int blk_trace_startstop(struct request_queue *q, int start)
 {
struct blk_trace *bt;
int ret;
@@ -453,6 +454,7 @@ static int blk_trace_startstop(struct re
 
return ret;
 }
+EXPORT_SYMBOL_GPL(blk_trace_startstop);
 
 /**
  * blk_trace_ioctl: - handle the ioctls associated with tracing
@@ -465,6 +467,7 @@ int blk_trace_ioctl(struct block_device 
 {
struct request_queue *q;
int ret, start = 0;
+   char b[BDEVNAME_SIZE];
 
q = bdev_get_queue(bdev);
if (!q)
@@ -474,7 +477,8 @@ int blk_trace_ioctl(struct block_device 
 
switch (cmd) {
case BLKTRACESETUP:
-   ret = blk_trace_setup(q, bdev, arg);
+   strcpy(b, bdevname(bdev, b));
+   ret = blk_trace_setup(q, b, bdev->bd_dev, arg);
break;
case BLKTRACESTART:
start = 1;
--- a/drivers/scsi/sg.c 2007-12-17 21:51:45.0 +0100
+++ b/drivers/scsi/sg.c 2007-12-17 22:36:30.0 +0100
@@ -48,6 +48,7 @@ static int sg_version_num = 30534;/* 2 
 #include 
 #include 
 #include 
+#include 
 
 #include "scsi.h"
 #include 
@@ -1063,6 +1064,17 @@ sg_ioctl(struct inode *inode, struct fil
case BLKSECTGET:
return put_user(sdp->device->request_queue->max_sectors * 512,
ip);
+   case BLKTRACESETUP:
+   return blk_trace_setup(sdp->device->request_queue,
+  sdp->disk->disk_name,
+  sdp->device->sdev_gendev.devt,
+  (char *)arg);
+   case BLKTRACESTART:
+   return blk_trace_startstop(sdp->device->request_queue, 1);
+   case BLKTRACESTOP:
+   return blk_trace_startstop(sdp->device->request_queue, 0);
+   case BLKTRACETEARDOWN:
+   return blk_trace_remove(sdp->device->request_queue);
default:
 

Re: [rfc][patch 1/3] block: non-atomic queue_flags prep

2007-12-18 Thread Nick Piggin
On Tue, Dec 18, 2007 at 08:44:40AM +0100, Jens Axboe wrote:
> On Sat, Dec 15 2007, Nick Piggin wrote:
> > Hi,
> > 
> > This is just an idea I had, which might make request processing a little
> > bit cheaper depending on queue behaviour. For example if it is getting 
> > plugged
> > unplugged frequently (as I think is the case for some database workloads),
> > then we might save one or two atomic operations per request.
> > 
> > Anyway, I'm not completely sure if I have ensured all queue_flags users are
> > safe (I think md may need a bit of help). But overall it seems quite doable.
> 
> Looks ok to me, I'll throw it into the testing mix. Thanks Nick!

OK... actually if you are expecting it to be widely tested, can you change
the BUG_ONs in queue_flag_set / queue_flag_clear into WARN_ON?

That way it's less likely to take down people's systems...

Thanks!
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html