Commit ea9339e5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata

Pull libata regression fix from Tejun Heo:
 "The last libata/for-3.16-fixes pull contained a regression introduced
  by 1871ee13 ("libata: support the ata host which implements a
  queue depth less than 32") which in turn was a fix for a regression
  introduced earlier while changing queue tag order to accomodate hard
  drives which perform poorly if tags are not allocated in circular
  order (ugh...).

  The regression happens only for SAS controllers making use of libata
  to serve ATA devices.  They don't fill an ata_host field which is used
  by the new tag allocation function leading to NULL dereference.

  This patch adds a new intermediate field ata_host->n_tags which is
  initialized for both SAS and !SAS cases to fix the issue"

* 'for-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  libata: introduce ata_host->n_tags to avoid oops on SAS controllers
parents b292d6b5 1a112d10
...@@ -4798,9 +4798,8 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) ...@@ -4798,9 +4798,8 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc = NULL; struct ata_queued_cmd *qc = NULL;
unsigned int i, tag, max_queue; unsigned int max_queue = ap->host->n_tags;
unsigned int i, tag;
max_queue = ap->scsi_host->can_queue;
/* no command while frozen */ /* no command while frozen */
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
...@@ -6094,6 +6093,7 @@ void ata_host_init(struct ata_host *host, struct device *dev, ...@@ -6094,6 +6093,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
{ {
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
mutex_init(&host->eh_mutex); mutex_init(&host->eh_mutex);
host->n_tags = ATA_MAX_QUEUE - 1;
host->dev = dev; host->dev = dev;
host->ops = ops; host->ops = ops;
} }
...@@ -6175,15 +6175,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ...@@ -6175,15 +6175,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
{ {
int i, rc; int i, rc;
/* host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1);
* The max queue supported by hardware must not be greater than
* ATA_MAX_QUEUE.
*/
if (sht->can_queue > ATA_MAX_QUEUE) {
dev_err(host->dev, "BUG: the hardware max queue is too large\n");
WARN_ON(1);
return -EINVAL;
}
/* host must have been started */ /* host must have been started */
if (!(host->flags & ATA_HOST_STARTED)) { if (!(host->flags & ATA_HOST_STARTED)) {
......
...@@ -593,6 +593,7 @@ struct ata_host { ...@@ -593,6 +593,7 @@ struct ata_host {
struct device *dev; struct device *dev;
void __iomem * const *iomap; void __iomem * const *iomap;
unsigned int n_ports; unsigned int n_ports;
unsigned int n_tags; /* nr of NCQ tags */
void *private_data; void *private_data;
struct ata_port_operations *ops; struct ata_port_operations *ops;
unsigned long flags; unsigned long flags;
......
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