From 7d37d6b6b293c6a9da19978d5918b71ebc4fb2c9 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 26 Jan 2016 02:47:01 +0800 Subject: devicetree: bindings: hisi_sas: add v2 HW bindings Add the dt bindings for HiSi SAS controller v2 HW. The main difference in the controller from dt perspective is interrupts. The v2 controller does not have dedicated fatal and broadcast interrupts - they are multiplexed on the channel interrupt. Each SAS v2 controller can issue upto 64 commands (or connection requests) on the system bus without waiting for a response - this is know as am-max-transmissions. In hip06, sas controller #1 has a limitation that it has to limit am-max-transmissions to 32 - this limitation is due to chip system bus design. It is not anticipated that any future chip incorporating v2 controller will have such a limitation. Signed-off-by: John Garry Reviewed-by: Hannes Reinecke Acked-by: Rob Herring Signed-off-by: Martin K. Petersen --- .../devicetree/bindings/scsi/hisilicon-sas.txt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt index f67e761bcc18..bf2411f366e5 100644 --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt @@ -5,6 +5,7 @@ The HiSilicon SAS controller supports SAS/SATA. Main node required properties: - compatible : value should be as follows: (a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset + (b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset - sas-addr : array of 8 bytes for host SAS address - reg : Address and length of the SAS register - hisilicon,sas-syscon: phandle of syscon used for sas control @@ -13,7 +14,7 @@ Main node required properties: - ctrl-clock-ena-reg : offset to controller clock enable register in ctrl reg - queue-count : number of delivery and completion queues in the controller - phy-count : number of phys accessible by the controller - - interrupts : Interrupts for phys, completion queues, and fatal + - interrupts : For v1 hw: Interrupts for phys, completion queues, and fatal sources; the interrupts are ordered in 3 groups, as follows: - Phy interrupts - Completion queue interrupts @@ -30,6 +31,24 @@ Main node required properties: Fatal interrupts : the fatal interrupts are ordered as follows: - ECC - AXI bus + For v2 hw: Interrupts for phys, Sata, and completion queues; + the interrupts are ordered in 3 groups, as follows: + - Phy interrupts + - Sata interrupts + - Completion queue interrupts + Phy interrupts : Each controller has 2 phy interrupts: + - phy up/down + - channel interrupt + Sata interrupts : Each phy on the controller has 1 Sata + interrupt. The interrupts are ordered in increasing + order. + Completion queue interrupts : each completion queue has 1 + interrupt source. The interrupts are ordered in + increasing order. + +Optional main node properties: + - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the + "am-max-transmissions" limitation. Example: sas0: sas@c1000000 { -- cgit v1.2.3 From 8038e6456a3e6f5c4759e0d73c4f9165b90c93e7 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Tue, 9 Feb 2016 21:56:55 +0200 Subject: st: Fix MTMKPART to work with newer drives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the MTMKPART operation of the MTIOCTOP ioctl so that it works also with current drives (LTO-5/6, etc.). Send a separate FORMAT MEDIUM command if the partition mode page indicates that this is required. Use LOAD to position the tape at the beginning of tape. The operation is extended so that if the argument is negative, its absolute value specifies the size of partition 0, which is the physically first partition of the tape. Signed-off-by: Kai Mäkisara Tested-by: Shane M Seymour Tested-by: Laurence Oberman Tested-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- Documentation/scsi/st.txt | 15 ++++-- drivers/scsi/st.c | 122 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 121 insertions(+), 16 deletions(-) (limited to 'Documentation') diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt index b3211af63b79..ec0acf6acccd 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.txt @@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara +Last modified: Tue Feb 9 21:54:16 2016 by kai.makisara BASICS @@ -408,10 +408,15 @@ MTSETPART Moves the tape to the partition given by the argument at the specified by MTSEEK. MTSETPART is inactive unless MT_ST_CAN_PARTITIONS set. MTMKPART Formats the tape with one partition (argument zero) or two - partitions (the argument gives in megabytes the size of - partition 1 that is physically the first partition of the - tape). The drive has to support partitions with size specified - by the initiator. Inactive unless MT_ST_CAN_PARTITIONS set. + partitions (argument non-zero). If the argument is positive, + it specifies the size of partition 1 in megabytes. For DDS + drives and several early drives this is the physically first + partition of the tape. If the argument is negative, its absolute + value specifies the size of partition 0 in megabytes. This is + the physically first partition of many later drives, like the + LTO drives from LTO-5 upwards. The drive has to support partitions + with size specified by the initiator. Inactive unless + MT_ST_CAN_PARTITIONS set. MTSETDRVBUFFER Is used for several purposes. The command is obtained from count with mask MT_SET_OPTIONS, the low order bits are used as argument. diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 2e522951b619..607b0a505844 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2010 Kai Makisara + Copyright 1992 - 2016 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20101219"; +static const char *verstr = "20160209"; #include @@ -3296,7 +3296,10 @@ static int switch_partition(struct scsi_tape *STp) #define PP_OFF_RESERVED 7 #define PP_BIT_IDP 0x20 +#define PP_BIT_FDP 0x80 #define PP_MSK_PSUM_MB 0x10 +#define PP_MSK_PSUM_UNITS 0x18 +#define PP_MSK_POFM 0x04 /* Get the number of partitions on the tape. As a side effect reads the mode page into the tape buffer. */ @@ -3322,6 +3325,29 @@ static int nbr_partitions(struct scsi_tape *STp) } +static int format_medium(struct scsi_tape *STp, int format) +{ + int result = 0; + int timeout = STp->long_timeout; + unsigned char scmd[MAX_COMMAND_SIZE]; + struct st_request *SRpnt; + + memset(scmd, 0, MAX_COMMAND_SIZE); + scmd[0] = FORMAT_UNIT; + scmd[2] = format; + if (STp->immediate) { + scmd[1] |= 1; /* Don't wait for completion */ + timeout = STp->device->request_queue->rq_timeout; + } + DEBC_printk(STp, "Sending FORMAT MEDIUM\n"); + SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE, + timeout, MAX_RETRIES, 1); + if (!SRpnt) + result = STp->buffer->syscall_result; + return result; +} + + /* Partition the tape into two partitions if size > 0 or one partition if size == 0. @@ -3340,11 +3366,16 @@ static int nbr_partitions(struct scsi_tape *STp) and 10 when 1 partition is defined (information from Eric Lee Green). This is is acceptable also to some other old drives and enforced if the first partition size field is used for the first additional partition size. + + For drives that advertize SCSI-3 or newer, use the SSC-3 methods. */ static int partition_tape(struct scsi_tape *STp, int size) { int result; + int target_partition; + bool scsi3 = STp->device->scsi_level >= SCSI_3, needs_format = false; int pgo, psd_cnt, psdo; + int psum = PP_MSK_PSUM_MB, units = 0; unsigned char *bp; result = read_mode_page(STp, PART_PAGE, 0); @@ -3352,6 +3383,12 @@ static int partition_tape(struct scsi_tape *STp, int size) DEBC_printk(STp, "Can't read partition mode page.\n"); return result; } + target_partition = 1; + if (size < 0) { + target_partition = 0; + size = -size; + } + /* The mode page is in the buffer. Let's modify it and write it. */ bp = (STp->buffer)->b_data; pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH]; @@ -3359,9 +3396,52 @@ static int partition_tape(struct scsi_tape *STp, int size) bp[pgo + MP_OFF_PAGE_LENGTH] + 2); psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2; + + if (scsi3) { + needs_format = (bp[pgo + PP_OFF_FLAGS] & PP_MSK_POFM) != 0; + if (needs_format && size == 0) { + /* No need to write the mode page when clearing + * partitioning + */ + DEBC_printk(STp, "Formatting tape with one partition.\n"); + result = format_medium(STp, 0); + goto out; + } + if (needs_format) /* Leave the old value for HP DATs claiming SCSI_3 */ + psd_cnt = 2; + if ((bp[pgo + PP_OFF_FLAGS] & PP_MSK_PSUM_UNITS) == PP_MSK_PSUM_UNITS) { + /* Use units scaling for large partitions if the device + * suggests it and no precision lost. Required for IBM + * TS1140/50 drives that don't support MB units. + */ + if (size >= 1000 && (size % 1000) == 0) { + size /= 1000; + psum = PP_MSK_PSUM_UNITS; + units = 9; /* GB */ + } + } + /* Try it anyway if too large to specify in MB */ + if (psum == PP_MSK_PSUM_MB && size >= 65534) { + size /= 1000; + psum = PP_MSK_PSUM_UNITS; + units = 9; /* GB */ + } + } + + if (size >= 65535 || /* Does not fit into two bytes */ + (target_partition == 0 && psd_cnt < 2)) { + result = -EINVAL; + goto out; + } + psdo = pgo + PART_PAGE_FIXED_LENGTH; - if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) { - bp[psdo] = bp[psdo + 1] = 0xff; /* Rest of the tape */ + /* The second condition is for HP DDS which use only one partition size + * descriptor + */ + if (target_partition > 0 && + (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS] || + bp[pgo + PP_OFF_MAX_ADD_PARTS] != 1)) { + bp[psdo] = bp[psdo + 1] = 0xff; /* Rest to partition 0 */ psdo += 2; } memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2); @@ -3370,7 +3450,7 @@ static int partition_tape(struct scsi_tape *STp, int size) psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS], bp[pgo + PP_OFF_NBR_ADD_PARTS]); - if (size <= 0) { + if (size == 0) { bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0; if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS]) bp[pgo + MP_OFF_PAGE_LENGTH] = 6; @@ -3378,22 +3458,37 @@ static int partition_tape(struct scsi_tape *STp, int size) } else { bp[psdo] = (size >> 8) & 0xff; bp[psdo + 1] = size & 0xff; + if (target_partition == 0) + bp[psdo + 2] = bp[psdo + 3] = 0xff; bp[pgo + 3] = 1; if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8) bp[pgo + MP_OFF_PAGE_LENGTH] = 8; - DEBC_printk(STp, "Formatting tape with two partitions " - "(1 = %d MB).\n", size); + DEBC_printk(STp, + "Formatting tape with two partitions (%i = %d MB).\n", + target_partition, units > 0 ? size * 1000 : size); } bp[pgo + PP_OFF_PART_UNITS] = 0; bp[pgo + PP_OFF_RESERVED] = 0; - bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB; + if (size != 1 || units != 0) { + bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | psum | + (bp[pgo + PP_OFF_FLAGS] & 0x07); + bp[pgo + PP_OFF_PART_UNITS] = units; + } else + bp[pgo + PP_OFF_FLAGS] = PP_BIT_FDP | + (bp[pgo + PP_OFF_FLAGS] & 0x1f); + bp[pgo + MP_OFF_PAGE_LENGTH] = 6 + psd_cnt * 2; result = write_mode_page(STp, PART_PAGE, 1); + + if (!result && needs_format) + result = format_medium(STp, 1); + if (result) { st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n"); result = (-EIO); } +out: return result; } @@ -3570,8 +3665,13 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) retval = (-EINVAL); goto out; } - if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 || - (i = partition_tape(STp, mtc.mt_count)) < 0) { + i = do_load_unload(STp, file, 1); + if (i < 0) { + retval = i; + goto out; + } + i = partition_tape(STp, mtc.mt_count); + if (i < 0) { retval = i; goto out; } @@ -3581,7 +3681,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) STp->ps[i].last_block_valid = 0; } STp->partition = STp->new_partition = 0; - STp->nbr_partitions = 1; /* Bad guess ?-) */ + STp->nbr_partitions = mtc.mt_count != 0 ? 2 : 1; STps->drv_block = STps->drv_file = 0; retval = 0; goto out; -- cgit v1.2.3