Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  Fix bug - Implement bfin ata interrupt handler to avoid "irq 68 nobody cared" (v2)
  sata_mv: Improve naming of main_irq cause/mask identifiers
  libata-scsi: improve rbuf handling for simulated commands
  libata-scsi: clean up inquiry / mode sense related functions
  [MIPS] ATA: Rename routerboard 500 to 532
This commit is contained in:
Linus Torvalds 2008-04-29 08:52:05 -07:00
commit c135b6592b
7 changed files with 365 additions and 459 deletions

View File

@ -566,11 +566,11 @@ config PATA_RADISYS
If unsure, say N.
config PATA_RB500
tristate "RouterBoard 500 PATA CompactFlash support"
depends on MIKROTIK_RB500
config PATA_RB532
tristate "RouterBoard 532 PATA CompactFlash support"
depends on MIKROTIK_RB532
help
This option enables support for the RouterBoard 500
This option enables support for the RouterBoard 532
PATA CompactFlash controller.
If unsure, say N.

View File

@ -55,7 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RB500) += pata_rb500_cf.o
obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o

View File

@ -49,7 +49,11 @@
#include "libata.h"
#define SECTOR_SIZE 512
#define SECTOR_SIZE 512
#define ATA_SCSI_RBUF_SIZE 4096
static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
@ -179,6 +183,13 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
ata_scsi_lpm_show, ata_scsi_lpm_put);
EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
@ -1632,53 +1643,48 @@ defer:
/**
* ata_scsi_rbuf_get - Map response buffer.
* @cmd: SCSI command containing buffer to be mapped.
* @buf_out: Pointer to mapped area.
* @flags: unsigned long variable to store irq enable status
* @copy_in: copy in from user buffer
*
* Maps buffer contained within SCSI command @cmd.
* Prepare buffer for simulated SCSI commands.
*
* LOCKING:
* spin_lock_irqsave(host lock)
* spin_lock_irqsave(ata_scsi_rbuf_lock) on success
*
* RETURNS:
* Length of response buffer.
* Pointer to response buffer.
*/
static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
unsigned long *flags)
{
u8 *buf;
unsigned int buflen;
spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);
struct scatterlist *sg = scsi_sglist(cmd);
if (sg) {
buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
buflen = sg->length;
} else {
buf = NULL;
buflen = 0;
}
*buf_out = buf;
return buflen;
memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
if (copy_in)
sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
return ata_scsi_rbuf;
}
/**
* ata_scsi_rbuf_put - Unmap response buffer.
* @cmd: SCSI command containing buffer to be unmapped.
* @buf: buffer to unmap
* @copy_out: copy out result
* @flags: @flags passed to ata_scsi_rbuf_get()
*
* Unmaps response buffer contained within @cmd.
* Returns rbuf buffer. The result is copied to @cmd's buffer if
* @copy_back is true.
*
* LOCKING:
* spin_lock_irqsave(host lock)
* Unlocks ata_scsi_rbuf_lock.
*/
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
unsigned long *flags)
{
struct scatterlist *sg = scsi_sglist(cmd);
if (sg)
kunmap_atomic(buf - sg->offset, KM_IRQ0);
if (copy_out)
sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
}
/**
@ -1696,51 +1702,27 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen))
static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
{
u8 *rbuf;
unsigned int buflen, rc;
unsigned int rc;
struct scsi_cmnd *cmd = args->cmd;
unsigned long flags;
local_irq_save(flags);
buflen = ata_scsi_rbuf_get(cmd, &rbuf);
memset(rbuf, 0, buflen);
rc = actor(args, rbuf, buflen);
ata_scsi_rbuf_put(cmd, rbuf);
local_irq_restore(flags);
rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
rc = actor(args, rbuf);
ata_scsi_rbuf_put(cmd, rc == 0, &flags);
if (rc == 0)
cmd->result = SAM_STAT_GOOD;
args->done(cmd);
}
/**
* ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
* @idx: byte index into SCSI response buffer
* @val: value to set
*
* To be used by SCSI command simulator functions. This macros
* expects two local variables, u8 *rbuf and unsigned int buflen,
* are in scope.
*
* LOCKING:
* None.
*/
#define ATA_SCSI_RBUF_SET(idx, val) do { \
if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
} while (0)
/**
* ata_scsiop_inq_std - Simulate INQUIRY command
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Returns standard device identification data associated
* with non-VPD INQUIRY command output.
@ -1748,10 +1730,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
{
const u8 versions[] = {
0x60, /* SAM-3 (no version claimed) */
0x03,
0x20, /* SBC-2 (no version claimed) */
0x02,
0x60 /* SPC-3 (no version claimed) */
};
u8 hdr[] = {
TYPE_DISK,
0,
@ -1760,35 +1749,21 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
95 - 4
};
VPRINTK("ENTER\n");
/* set scsi removeable (RMB) bit per ata bit */
if (ata_id_removeable(args->id))
hdr[1] |= (1 << 7);
VPRINTK("ENTER\n");
memcpy(rbuf, hdr, sizeof(hdr));
memcpy(&rbuf[8], "ATA ", 8);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
if (buflen > 35) {
memcpy(&rbuf[8], "ATA ", 8);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
}
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
if (buflen > 63) {
const u8 versions[] = {
0x60, /* SAM-3 (no version claimed) */
0x03,
0x20, /* SBC-2 (no version claimed) */
0x02,
0x60 /* SPC-3 (no version claimed) */
};
memcpy(rbuf + 59, versions, sizeof(versions));
}
memcpy(rbuf + 59, versions, sizeof(versions));
return 0;
}
@ -1797,27 +1772,22 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Returns list of inquiry VPD pages available.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
{
const u8 pages[] = {
0x00, /* page 0x00, this page */
0x80, /* page 0x80, unit serial no page */
0x83 /* page 0x83, device ident page */
};
rbuf[3] = sizeof(pages); /* number of supported VPD pages */
if (buflen > 6)
memcpy(rbuf + 4, pages, sizeof(pages));
memcpy(rbuf + 4, pages, sizeof(pages));
return 0;
}
@ -1825,16 +1795,13 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Returns ATA device serial number.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
{
const u8 hdr[] = {
0,
@ -1842,12 +1809,10 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
0,
ATA_ID_SERNO_LEN, /* page len */
};
memcpy(rbuf, hdr, sizeof(hdr));
if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
ata_id_string(args->id, (unsigned char *) &rbuf[4],
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
ata_id_string(args->id, (unsigned char *) &rbuf[4],
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
return 0;
}
@ -1855,7 +1820,6 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Yields two logical unit device identification designators:
* - vendor specific ASCII containing the ATA serial number
@ -1865,41 +1829,37 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
{
int num;
const int sat_model_serial_desc_len = 68;
int num;
rbuf[1] = 0x83; /* this page code */
num = 4;
if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
/* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
rbuf[num + 0] = 2;
rbuf[num + 3] = ATA_ID_SERNO_LEN;
num += 4;
ata_id_string(args->id, (unsigned char *) rbuf + num,
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
}
if (buflen > (sat_model_serial_desc_len + num + 3)) {
/* SAT defined lu model and serial numbers descriptor */
/* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
rbuf[num + 0] = 2;
rbuf[num + 1] = 1;
rbuf[num + 3] = sat_model_serial_desc_len;
num += 4;
memcpy(rbuf + num, "ATA ", 8);
num += 8;
ata_id_string(args->id, (unsigned char *) rbuf + num,
ATA_ID_PROD, ATA_ID_PROD_LEN);
num += ATA_ID_PROD_LEN;
ata_id_string(args->id, (unsigned char *) rbuf + num,
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
}
/* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
rbuf[num + 0] = 2;
rbuf[num + 3] = ATA_ID_SERNO_LEN;
num += 4;
ata_id_string(args->id, (unsigned char *) rbuf + num,
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
/* SAT defined lu model and serial numbers descriptor */
/* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
rbuf[num + 0] = 2;
rbuf[num + 1] = 1;
rbuf[num + 3] = sat_model_serial_desc_len;
num += 4;
memcpy(rbuf + num, "ATA ", 8);
num += 8;
ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
ATA_ID_PROD_LEN);
num += ATA_ID_PROD_LEN;
ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
return 0;
}
@ -1908,35 +1868,26 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Yields SAT-specified ATA VPD page.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
{
u8 pbuf[60];
struct ata_taskfile tf;
unsigned int i;
if (!buflen)
return 0;
memset(&pbuf, 0, sizeof(pbuf));
memset(&tf, 0, sizeof(tf));
pbuf[1] = 0x89; /* our page code */
pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
pbuf[3] = (0x238 & 0xff);
rbuf[1] = 0x89; /* our page code */
rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
rbuf[3] = (0x238 & 0xff);
memcpy(&pbuf[8], "linux ", 8);
memcpy(&pbuf[16], "libata ", 16);
memcpy(&pbuf[32], DRV_VERSION, 4);
ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
memcpy(&rbuf[8], "linux ", 8);
memcpy(&rbuf[16], "libata ", 16);
memcpy(&rbuf[32], DRV_VERSION, 4);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
/* we don't store the ATA device signature, so we fake it */
@ -1944,19 +1895,12 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
tf.lbal = 0x1;
tf.nsect = 0x1;
ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */
pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
ata_tf_to_fis(&tf, 0, 1, &rbuf[36]); /* TODO: PMP? */
rbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
pbuf[56] = ATA_CMD_ID_ATA;
rbuf[56] = ATA_CMD_ID_ATA;
i = min(buflen, 60U);
memcpy(rbuf, &pbuf[0], i);
buflen -= i;
if (!buflen)
return 0;
memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
memcpy(&rbuf[60], &args->id[0], 512);
return 0;
}
@ -1964,7 +1908,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* No operation. Simply returns success to caller, to indicate
* that the caller should successfully complete this SCSI command.
@ -1972,47 +1915,16 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
{
VPRINTK("ENTER\n");
return 0;
}
/**
* ata_msense_push - Push data onto MODE SENSE data output buffer
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* @buf: Pointer to BLOB being added to output buffer
* @buflen: Length of BLOB
*
* Store MODE SENSE data on an output buffer.
*
* LOCKING:
* None.
*/
static void ata_msense_push(u8 **ptr_io, const u8 *last,
const u8 *buf, unsigned int buflen)
{
u8 *ptr = *ptr_io;
if ((ptr + buflen - 1) > last)
return;
memcpy(ptr, buf, buflen);
ptr += buflen;
*ptr_io = ptr;
}
/**
* ata_msense_caching - Simulate MODE SENSE caching info page
* @id: device IDENTIFY data
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* @buf: output buffer
*
* Generate a caching info page, which conditionally indicates
* write caching to the SCSI layer, depending on device
@ -2021,58 +1933,43 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
* LOCKING:
* None.
*/
static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
const u8 *last)
static unsigned int ata_msense_caching(u16 *id, u8 *buf)
{
u8 page[CACHE_MPAGE_LEN];
memcpy(page, def_cache_mpage, sizeof(page));
memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
if (ata_id_wcache_enabled(id))
page[2] |= (1 << 2); /* write cache enable */
buf[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id))
page[12] |= (1 << 5); /* disable read ahead */
ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page);
buf[12] |= (1 << 5); /* disable read ahead */
return sizeof(def_cache_mpage);
}
/**
* ata_msense_ctl_mode - Simulate MODE SENSE control mode page
* @dev: Device associated with this MODE SENSE command
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* @buf: output buffer
*
* Generate a generic MODE SENSE control mode page.
*
* LOCKING:
* None.
*/
static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
static unsigned int ata_msense_ctl_mode(u8 *buf)
{
ata_msense_push(ptr_io, last, def_control_mpage,
sizeof(def_control_mpage));
memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
return sizeof(def_control_mpage);
}
/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @dev: Device associated with this MODE SENSE command
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* @bufp: output buffer
*
* Generate a generic MODE SENSE r/w error recovery page.
*
* LOCKING:
* None.
*/
static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
static unsigned int ata_msense_rw_recovery(u8 *buf)
{
ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
sizeof(def_rw_recovery_mpage));
memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
return sizeof(def_rw_recovery_mpage);
}
@ -2104,7 +2001,6 @@ static int ata_dev_supports_fua(u16 *id)
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Simulate MODE SENSE commands. Assume this is invoked for direct
* access devices (e.g. disks) only. There should be no block
@ -2113,19 +2009,17 @@ static int ata_dev_supports_fua(u16 *id)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
{
struct ata_device *dev = args->dev;
u8 *scsicmd = args->cmd->cmnd, *p, *last;
u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */
0,
0, 0x2, 0x0 /* block length: 512 bytes */
};
u8 pg, spg;
unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
unsigned int ebd, page_control, six_byte;
u8 dpofua;
VPRINTK("ENTER\n");
@ -2148,17 +2042,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
goto invalid_fld;
}
if (six_byte) {
output_len = 4 + (ebd ? 8 : 0);
alloc_len = scsicmd[4];
} else {
output_len = 8 + (ebd ? 8 : 0);
alloc_len = (scsicmd[7] << 8) + scsicmd[8];
}
minlen = (alloc_len < buflen) ? alloc_len : buflen;
p = rbuf + output_len;
last = rbuf + minlen - 1;
if (six_byte)
p += 4 + (ebd ? 8 : 0);
else
p += 8 + (ebd ? 8 : 0);
pg = scsicmd[2] & 0x3f;
spg = scsicmd[3];
@ -2171,61 +2058,48 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
switch(pg) {
case RW_RECOVERY_MPAGE:
output_len += ata_msense_rw_recovery(&p, last);
p += ata_msense_rw_recovery(p);
break;
case CACHE_MPAGE:
output_len += ata_msense_caching(args->id, &p, last);
p += ata_msense_caching(args->id, p);
break;
case CONTROL_MPAGE: {
output_len += ata_msense_ctl_mode(&p, last);
case CONTROL_MPAGE:
p += ata_msense_ctl_mode(p);
break;
}
case ALL_MPAGES:
output_len += ata_msense_rw_recovery(&p, last);
output_len += ata_msense_caching(args->id, &p, last);
output_len += ata_msense_ctl_mode(&p, last);
p += ata_msense_rw_recovery(p);
p += ata_msense_caching(args->id, p);
p += ata_msense_ctl_mode(p);
break;
default: /* invalid page code */
goto invalid_fld;
}
if (minlen < 1)
return 0;
dpofua = 0;
if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
(!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
dpofua = 1 << 4;
if (six_byte) {
output_len--;
rbuf[0] = output_len;
if (minlen > 2)
rbuf[2] |= dpofua;
rbuf[0] = p - rbuf - 1;
rbuf[2] |= dpofua;
if (ebd) {
if (minlen > 3)
rbuf[3] = sizeof(sat_blk_desc);
if (minlen > 11)
memcpy(rbuf + 4, sat_blk_desc,
sizeof(sat_blk_desc));
rbuf[3] = sizeof(sat_blk_desc);
memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
}
} else {
output_len -= 2;
unsigned int output_len = p - rbuf - 2;
rbuf[0] = output_len >> 8;
if (minlen > 1)
rbuf[1] = output_len;
if (minlen > 3)
rbuf[3] |= dpofua;
rbuf[1] = output_len;
rbuf[3] |= dpofua;
if (ebd) {
if (minlen > 7)
rbuf[7] = sizeof(sat_blk_desc);
if (minlen > 15)
memcpy(rbuf + 8, sat_blk_desc,
sizeof(sat_blk_desc));
rbuf[7] = sizeof(sat_blk_desc);
memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
}
}
return 0;
@ -2245,15 +2119,13 @@ saving_not_supp:
* ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Simulate READ CAPACITY commands.
*
* LOCKING:
* None.
*/
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
{
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
@ -2264,28 +2136,28 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
last_lba = 0xffffffff;
/* sector count, 32-bit */
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3));
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2));
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1));
ATA_SCSI_RBUF_SET(3, last_lba);
rbuf[0] = last_lba >> (8 * 3);
rbuf[1] = last_lba >> (8 * 2);
rbuf[2] = last_lba >> (8 * 1);
rbuf[3] = last_lba;
/* sector size */
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
rbuf[6] = ATA_SECT_SIZE >> 8;
rbuf[7] = ATA_SECT_SIZE & 0xff;
} else {
/* sector count, 64-bit */
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6));
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5));
ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4));
ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3));
ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2));
ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1));
ATA_SCSI_RBUF_SET(7, last_lba);
rbuf[0] = last_lba >> (8 * 7);
rbuf[1] = last_lba >> (8 * 6);
rbuf[2] = last_lba >> (8 * 5);
rbuf[3] = last_lba >> (8 * 4);
rbuf[4] = last_lba >> (8 * 3);
rbuf[5] = last_lba >> (8 * 2);
rbuf[6] = last_lba >> (8 * 1);
rbuf[7] = last_lba;
/* sector size */
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
rbuf[10] = ATA_SECT_SIZE >> 8;
rbuf[11] = ATA_SECT_SIZE & 0xff;
}
return 0;
@ -2295,16 +2167,13 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_report_luns - Simulate REPORT LUNS command
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Simulate REPORT LUNS command.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
{
VPRINTK("ENTER\n");
rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
@ -2312,53 +2181,6 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
return 0;
}
/**
* ata_scsi_set_sense - Set SCSI sense data and status
* @cmd: SCSI request to be handled
* @sk: SCSI-defined sense key
* @asc: SCSI-defined additional sense code
* @ascq: SCSI-defined additional sense code qualifier
*
* Helper function that builds a valid fixed format, current
* response code and the given sense key (sk), additional sense
* code (asc) and additional sense code qualifier (ascq) with
* a SCSI command status of %SAM_STAT_CHECK_CONDITION and
* DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
*
* LOCKING:
* Not required
*/
void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
/**
* ata_scsi_badcmd - End a SCSI request with an error
* @cmd: SCSI request to be handled
* @done: SCSI command completion function
* @asc: SCSI-defined additional sense code
* @ascq: SCSI-defined additional sense code qualifier
*
* Helper function that completes a SCSI command with
* %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
* and the specified additional sense codes.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{
DPRINTK("ENTER\n");
ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
done(cmd);
}
static void atapi_sense_complete(struct ata_queued_cmd *qc)
{
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
@ -2485,13 +2307,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
u8 *scsicmd = cmd->cmnd;
if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
u8 *buf = NULL;
unsigned int buflen;
unsigned long flags;
u8 *buf;
local_irq_save(flags);
buflen = ata_scsi_rbuf_get(cmd, &buf);
buf = ata_scsi_rbuf_get(cmd, true, &flags);
/* ATAPI devices typically report zero for their SCSI version,
* and sometimes deviate from the spec WRT response data
@ -2506,9 +2325,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
buf[3] = 0x32;
}
ata_scsi_rbuf_put(cmd, buf);
local_irq_restore(flags);
ata_scsi_rbuf_put(cmd, true, &flags);
}
cmd->result = SAM_STAT_GOOD;

View File

@ -146,34 +146,6 @@ extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_media_change_notify(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap);

View File

@ -1272,8 +1272,8 @@ static void bfin_freeze(struct ata_port *ap)
void bfin_thaw(struct ata_port *ap)
{
dev_dbg(ap->dev, "in atapi dma thaw\n");
bfin_check_status(ap);
bfin_irq_clear(ap);
bfin_irq_on(ap);
}
@ -1339,13 +1339,130 @@ static int bfin_port_start(struct ata_port *ap)
return 0;
}
static unsigned int bfin_ata_host_intr(struct ata_port *ap,
struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
u8 status, host_stat = 0;
VPRINTK("ata%u: protocol %d task_state %d\n",
ap->print_id, qc->tf.protocol, ap->hsm_task_state);
/* Check whether we are expecting interrupt in this state */
switch (ap->hsm_task_state) {
case HSM_ST_FIRST:
/* Some pre-ATAPI-4 devices assert INTRQ
* at this state when ready to receive CDB.
*/
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
* The flag was turned on only for atapi devices.
* No need to check is_atapi_taskfile(&qc->tf) again.
*/
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto idle_irq;
break;
case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATAPI_PROT_DMA) {
/* check status of DMA engine */
host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n",
ap->print_id, host_stat);
/* if it's not our irq... */
if (!(host_stat & ATA_DMA_INTR))
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
ap->ops->bmdma_stop(qc);
if (unlikely(host_stat & ATA_DMA_ERR)) {
/* error when transfering data to/from memory */
qc->err_mask |= AC_ERR_HOST_BUS;
ap->hsm_task_state = HSM_ST_ERR;
}
}
break;
case HSM_ST:
break;
default:
goto idle_irq;
}
/* check altstatus */
status = ap->ops->sff_check_altstatus(ap);
if (status & ATA_BUSY)
goto busy_ata;
/* check main status, clearing INTRQ */
status = ap->ops->sff_check_status(ap);
if (unlikely(status & ATA_BUSY))
goto busy_ata;
/* ack bmdma irq events */
ap->ops->sff_irq_clear(ap);
ata_sff_hsm_move(ap, qc, status, 0);
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATAPI_PROT_DMA))
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
busy_ata:
return 1; /* irq handled */
idle_irq:
ap->stats.idle_irq++;
#ifdef ATA_IRQ_TRAP
if ((ap->stats.idle_irq % 1000) == 0) {
ap->ops->irq_ack(ap, 0); /* debug trap */
ata_port_printk(ap, KERN_WARNING, "irq trap\n");
return 1;
}
#endif
return 0; /* irq not handled */
}
static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
unsigned int handled = 0;
unsigned long flags;
/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
spin_lock_irqsave(&host->lock, flags);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
ap = host->ports[i];
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
(qc->flags & ATA_QCFLAG_ACTIVE))
handled |= bfin_ata_host_intr(ap, qc);
}
}
spin_unlock_irqrestore(&host->lock, flags);
return IRQ_RETVAL(handled);
}
static struct scsi_host_template bfin_sht = {
ATA_BASE_SHT(DRV_NAME),
.sg_tablesize = SG_NONE,
.dma_boundary = ATA_DMA_BOUNDARY,
};
static const struct ata_port_operations bfin_pata_ops = {
static struct ata_port_operations bfin_pata_ops = {
.inherits = &ata_sff_port_ops,
.set_piomode = bfin_set_piomode,
@ -1370,7 +1487,6 @@ static const struct ata_port_operations bfin_pata_ops = {
.thaw = bfin_thaw,
.softreset = bfin_softreset,
.postreset = bfin_postreset,
.post_internal_cmd = bfin_bmdma_stop,
.sff_irq_clear = bfin_irq_clear,
.sff_irq_on = bfin_irq_on,
@ -1507,7 +1623,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
}
if (ata_host_activate(host, platform_get_irq(pdev, 0),
ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
peripheral_free_list(atapi_io_port);
dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
return -ENODEV;

View File

@ -32,7 +32,7 @@
#include <asm/gpio.h>
#define DRV_NAME "pata-rb500-cf"
#define DRV_NAME "pata-rb532-cf"
#define DRV_VERSION "0.1.0"
#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
@ -43,7 +43,7 @@
#define RB500_CF_REG_CTRL 0x080E
#define RB500_CF_REG_DATA 0x0C00
struct rb500_cf_info {
struct rb532_cf_info {
void __iomem *iobase;
unsigned int gpio_line;
int frozen;
@ -52,10 +52,10 @@ struct rb500_cf_info {
/* ------------------------------------------------------------------------ */
static inline void rb500_pata_finish_io(struct ata_port *ap)
static inline void rb532_pata_finish_io(struct ata_port *ap)
{
struct ata_host *ah = ap->host;
struct rb500_cf_info *info = ah->private_data;
struct rb532_cf_info *info = ah->private_data;
ata_sff_altstatus(ap);
ndelay(RB500_CF_IO_DELAY);
@ -63,14 +63,14 @@ static inline void rb500_pata_finish_io(struct ata_port *ap)
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
}
static void rb500_pata_exec_command(struct ata_port *ap,
static void rb532_pata_exec_command(struct ata_port *ap,
const struct ata_taskfile *tf)
{
writeb(tf->command, ap->ioaddr.command_addr);
rb500_pata_finish_io(ap);
rb532_pata_finish_io(ap);
}
static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
struct ata_port *ap = adev->link->ap;
@ -84,27 +84,27 @@ static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
*buf = readb(ioaddr);
}
rb500_pata_finish_io(adev->link->ap);
rb532_pata_finish_io(adev->link->ap);
}
static void rb500_pata_freeze(struct ata_port *ap)
static void rb532_pata_freeze(struct ata_port *ap)
{
struct rb500_cf_info *info = ap->host->private_data;
struct rb532_cf_info *info = ap->host->private_data;
info->frozen = 1;
}
static void rb500_pata_thaw(struct ata_port *ap)
static void rb532_pata_thaw(struct ata_port *ap)
{
struct rb500_cf_info *info = ap->host->private_data;
struct rb532_cf_info *info = ap->host->private_data;
info->frozen = 0;
}
static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
{
struct ata_host *ah = dev_instance;
struct rb500_cf_info *info = ah->private_data;
struct rb532_cf_info *info = ah->private_data;
if (gpio_get_value(info->gpio_line)) {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
@ -117,30 +117,30 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
return IRQ_HANDLED;
}
static struct ata_port_operations rb500_pata_port_ops = {
static struct ata_port_operations rb532_pata_port_ops = {
.inherits = &ata_sff_port_ops,
.sff_exec_command = rb500_pata_exec_command,
.sff_data_xfer = rb500_pata_data_xfer,
.freeze = rb500_pata_freeze,
.thaw = rb500_pata_thaw,
.sff_exec_command = rb532_pata_exec_command,
.sff_data_xfer = rb532_pata_data_xfer,
.freeze = rb532_pata_freeze,
.thaw = rb532_pata_thaw,
};
/* ------------------------------------------------------------------------ */
static struct scsi_host_template rb500_pata_sht = {
static struct scsi_host_template rb532_pata_sht = {
ATA_PIO_SHT(DRV_NAME),
};
/* ------------------------------------------------------------------------ */
static void rb500_pata_setup_ports(struct ata_host *ah)
static void rb532_pata_setup_ports(struct ata_host *ah)
{
struct rb500_cf_info *info = ah->private_data;
struct rb532_cf_info *info = ah->private_data;
struct ata_port *ap;
ap = ah->ports[0];
ap->ops = &rb500_pata_port_ops;
ap->ops = &rb532_pata_port_ops;
ap->pio_mask = 0x1f; /* PIO4 */
ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
@ -153,13 +153,13 @@ static void rb500_pata_setup_ports(struct ata_host *ah)
ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
}
static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
{
unsigned int irq;
int gpio;
struct resource *res;
struct ata_host *ah;
struct rb500_cf_info *info;
struct rb532_cf_info *info;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -213,10 +213,10 @@ static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
goto err_free_gpio;
}
rb500_pata_setup_ports(ah);
rb532_pata_setup_ports(ah);
ret = ata_host_activate(ah, irq, rb500_pata_irq_handler,
IRQF_TRIGGER_LOW, &rb500_pata_sht);
ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
IRQF_TRIGGER_LOW, &rb532_pata_sht);
if (ret)
goto err_free_gpio;
@ -228,10 +228,10 @@ err_free_gpio:
return ret;
}
static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
{
struct ata_host *ah = platform_get_drvdata(pdev);
struct rb500_cf_info *info = ah->private_data;
struct rb532_cf_info *info = ah->private_data;
ata_host_detach(ah);
gpio_free(info->gpio_line);
@ -242,9 +242,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" DRV_NAME);
static struct platform_driver rb500_pata_platform_driver = {
.probe = rb500_pata_driver_probe,
.remove = __devexit_p(rb500_pata_driver_remove),
static struct platform_driver rb532_pata_platform_driver = {
.probe = rb532_pata_driver_probe,
.remove = __devexit_p(rb532_pata_driver_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
@ -255,16 +255,16 @@ static struct platform_driver rb500_pata_platform_driver = {
#define DRV_INFO DRV_DESC " version " DRV_VERSION
static int __init rb500_pata_module_init(void)
static int __init rb532_pata_module_init(void)
{
printk(KERN_INFO DRV_INFO "\n");
return platform_driver_register(&rb500_pata_platform_driver);
return platform_driver_register(&rb532_pata_platform_driver);
}
static void __exit rb500_pata_module_exit(void)
static void __exit rb532_pata_module_exit(void)
{
platform_driver_unregister(&rb500_pata_platform_driver);
platform_driver_unregister(&rb532_pata_platform_driver);
}
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
@ -273,5 +273,5 @@ MODULE_DESCRIPTION(DRV_DESC);
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
module_init(rb500_pata_module_init);
module_exit(rb500_pata_module_exit);
module_init(rb532_pata_module_init);
module_exit(rb532_pata_module_exit);

View File

@ -172,10 +172,11 @@ enum {
PCIE_IRQ_MASK_OFS = 0x1910,
PCIE_UNMASK_ALL_IRQS = 0x40a, /* assorted bits */
HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
HC_MAIN_IRQ_MASK_OFS = 0x1d64,
HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
/* Host Controller Main Interrupt Cause/Mask registers (1 per-chip) */
PCI_HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64,
SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024,
ERR_IRQ = (1 << 0), /* shift by port # */
DONE_IRQ = (1 << 1), /* shift by port # */
HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
@ -445,8 +446,8 @@ struct mv_host_priv {
const struct mv_hw_ops *ops;
int n_ports;
void __iomem *base;
void __iomem *main_cause_reg_addr;
void __iomem *main_mask_reg_addr;
void __iomem *main_irq_cause_addr;
void __iomem *main_irq_mask_addr;
u32 irq_cause_ofs;
u32 irq_mask_ofs;
u32 unmask_all_irqs;
@ -727,8 +728,8 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
* Simple code, with two return values, so macro rather than inline.
*
* port is the sole input, in range 0..7.
* shift is one output, for use with the main_cause and main_mask registers.
* hardport is the other output, in range 0..3
* shift is one output, for use with main_irq_cause / main_irq_mask registers.
* hardport is the other output, in range 0..3.
*
* Note that port and hardport may be the same variable in some cases.
*/
@ -1679,12 +1680,12 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
/**
* mv_host_intr - Handle all interrupts on the given host controller
* @host: host specific structure
* @main_cause: Main interrupt cause register for the chip.
* @main_irq_cause: Main interrupt cause register for the chip.
*
* LOCKING:
* Inherited from caller.
*/
static int mv_host_intr(struct ata_host *host, u32 main_cause)
static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
{
struct mv_host_priv *hpriv = host->private_data;
void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
@ -1705,7 +1706,7 @@ static int mv_host_intr(struct ata_host *host, u32 main_cause)
* Do nothing if port is not interrupting or is disabled:
*/
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ);
port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
continue;
/*
@ -1811,20 +1812,20 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance;
struct mv_host_priv *hpriv = host->private_data;
unsigned int handled = 0;
u32 main_cause, main_mask;
u32 main_irq_cause, main_irq_mask;
spin_lock(&host->lock);
main_cause = readl(hpriv->main_cause_reg_addr);
main_mask = readl(hpriv->main_mask_reg_addr);
main_irq_cause = readl(hpriv->main_irq_cause_addr);
main_irq_mask = readl(hpriv->main_irq_mask_addr);
/*
* Deal with cases where we either have nothing pending, or have read
* a bogus register value which can indicate HW removal or PCI fault.
*/
if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) {
if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host)))
if ((main_irq_cause & main_irq_mask) && (main_irq_cause != 0xffffffffU)) {
if (unlikely((main_irq_cause & PCI_ERR) && HAS_PCI(host)))
handled = mv_pci_error(host, hpriv->base);
else
handled = mv_host_intr(host, main_cause);
handled = mv_host_intr(host, main_irq_cause);
}
spin_unlock(&host->lock);
return IRQ_RETVAL(handled);
@ -2027,7 +2028,7 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
ZERO(MV_PCI_DISC_TIMER);
ZERO(MV_PCI_MSI_TRIGGER);
writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
ZERO(HC_MAIN_IRQ_MASK_OFS);
ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
ZERO(MV_PCI_SERR_MASK);
ZERO(hpriv->irq_cause_ofs);
ZERO(hpriv->irq_mask_ofs);
@ -2404,7 +2405,7 @@ static void mv_eh_freeze(struct ata_port *ap)
{
struct mv_host_priv *hpriv = ap->host->private_data;
unsigned int shift, hardport, port = ap->port_no;
u32 main_mask;
u32 main_irq_mask;
/* FIXME: handle coalescing completion events properly */
@ -2412,9 +2413,9 @@ static void mv_eh_freeze(struct ata_port *ap)
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
/* disable assertion of portN err, done events */
main_mask = readl(hpriv->main_mask_reg_addr);
main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_mask, hpriv->main_mask_reg_addr);
main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
}
static void mv_eh_thaw(struct ata_port *ap)
@ -2423,7 +2424,7 @@ static void mv_eh_thaw(struct ata_port *ap)
unsigned int shift, hardport, port = ap->port_no;
void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
void __iomem *port_mmio = mv_ap_base(ap);
u32 main_mask, hc_irq_cause;
u32 main_irq_mask, hc_irq_cause;
/* FIXME: handle coalescing completion events properly */
@ -2438,9 +2439,9 @@ static void mv_eh_thaw(struct ata_port *ap)
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
/* enable assertion of portN err, done events */
main_mask = readl(hpriv->main_mask_reg_addr);
main_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_mask, hpriv->main_mask_reg_addr);
main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
}
/**
@ -2654,15 +2655,15 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
goto done;
if (HAS_PCI(host)) {
hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_mask_reg_addr = mmio + HC_MAIN_IRQ_MASK_OFS;
hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
} else {
hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_mask_reg_addr = mmio + HC_SOC_MAIN_IRQ_MASK_OFS;
hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
}
/* global interrupt mask: 0 == mask everything */
writel(0, hpriv->main_mask_reg_addr);
writel(0, hpriv->main_irq_mask_addr);
n_hc = mv_get_hc_count(host->ports[0]->flags);
@ -2712,23 +2713,23 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
if (IS_GEN_I(hpriv))
writelfl(~HC_MAIN_MASKED_IRQS_5,
hpriv->main_mask_reg_addr);
hpriv->main_irq_mask_addr);
else
writelfl(~HC_MAIN_MASKED_IRQS,
hpriv->main_mask_reg_addr);
hpriv->main_irq_mask_addr);
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
"PCI int cause/mask=0x%08x/0x%08x\n",
readl(hpriv->main_cause_reg_addr),
readl(hpriv->main_mask_reg_addr),
readl(hpriv->main_irq_cause_addr),
readl(hpriv->main_irq_mask_addr),
readl(mmio + hpriv->irq_cause_ofs),
readl(mmio + hpriv->irq_mask_ofs));
} else {
writelfl(~HC_MAIN_MASKED_IRQS_SOC,
hpriv->main_mask_reg_addr);
hpriv->main_irq_mask_addr);
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
readl(hpriv->main_cause_reg_addr),
readl(hpriv->main_mask_reg_addr));
readl(hpriv->main_irq_cause_addr),
readl(hpriv->main_irq_mask_addr));
}
done:
return rc;