Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: NCQ encapsulation for ZAC MANAGEMENT OUT

Add NCQ encapsulation for ZAC MANAGEMENT OUT and evaluate
NCQ Non-Data log pages to figure out if NCQ encapsulation
is supported.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Hannes Reinecke and committed by
Tejun Heo
284b3b77 27708a95

+70 -8
+40 -3
drivers/ata/libata-core.c
··· 2121 2121 } 2122 2122 } 2123 2123 2124 + static void ata_dev_config_ncq_non_data(struct ata_device *dev) 2125 + { 2126 + struct ata_port *ap = dev->link->ap; 2127 + unsigned int err_mask; 2128 + int log_index = ATA_LOG_NCQ_NON_DATA * 2; 2129 + u16 log_pages; 2130 + 2131 + err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY, 2132 + 0, ap->sector_buf, 1); 2133 + if (err_mask) { 2134 + ata_dev_dbg(dev, 2135 + "failed to get Log Directory Emask 0x%x\n", 2136 + err_mask); 2137 + return; 2138 + } 2139 + log_pages = get_unaligned_le16(&ap->sector_buf[log_index]); 2140 + if (!log_pages) { 2141 + ata_dev_warn(dev, 2142 + "NCQ Send/Recv Log not supported\n"); 2143 + return; 2144 + } 2145 + err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_NON_DATA, 2146 + 0, ap->sector_buf, 1); 2147 + if (err_mask) { 2148 + ata_dev_dbg(dev, 2149 + "failed to get NCQ Non-Data Log Emask 0x%x\n", 2150 + err_mask); 2151 + } else { 2152 + u8 *cmds = dev->ncq_non_data_cmds; 2153 + 2154 + memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_NON_DATA_SIZE); 2155 + } 2156 + } 2157 + 2124 2158 static int ata_dev_config_ncq(struct ata_device *dev, 2125 2159 char *desc, size_t desc_sz) 2126 2160 { ··· 2199 2165 snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth, 2200 2166 ddepth, aa_desc); 2201 2167 2202 - if ((ap->flags & ATA_FLAG_FPDMA_AUX) && 2203 - ata_id_has_ncq_send_and_recv(dev->id)) 2204 - ata_dev_config_ncq_send_recv(dev); 2168 + if ((ap->flags & ATA_FLAG_FPDMA_AUX)) { 2169 + if (ata_id_has_ncq_send_and_recv(dev->id)) 2170 + ata_dev_config_ncq_send_recv(dev); 2171 + if (ata_id_has_ncq_non_data(dev->id)) 2172 + ata_dev_config_ncq_non_data(dev); 2173 + } 2205 2174 2206 2175 return 0; 2207 2176 }
+13 -5
drivers/ata/libata-scsi.c
··· 3506 3506 3507 3507 reset_all = cdb[14] & 0x1; 3508 3508 3509 - tf->protocol = ATA_PROT_NODATA; 3510 - tf->command = ATA_CMD_ZAC_MGMT_OUT; 3511 - tf->feature = sa; 3512 - tf->hob_feature = reset_all & 0x1; 3513 - 3509 + if (ata_ncq_enabled(qc->dev) && 3510 + ata_fpdma_zac_mgmt_out_supported(qc->dev)) { 3511 + tf->protocol = ATA_PROT_NCQ; 3512 + tf->command = ATA_CMD_NCQ_NON_DATA; 3513 + tf->hob_nsect = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; 3514 + tf->nsect = qc->tag << 3; 3515 + tf->auxiliary = sa | (reset_all & 0x1) << 8; 3516 + } else { 3517 + tf->protocol = ATA_PROT_NODATA; 3518 + tf->command = ATA_CMD_ZAC_MGMT_OUT; 3519 + tf->feature = sa; 3520 + tf->hob_feature = reset_all & 0x1; 3521 + } 3514 3522 tf->lbah = (block >> 16) & 0xff; 3515 3523 tf->lbam = (block >> 8) & 0xff; 3516 3524 tf->lbal = block & 0xff;
+3
drivers/ata/libata-trace.c
··· 188 188 case ATA_SUBCMD_NCQ_NON_DATA_ZERO_EXT: 189 189 trace_seq_printf(p, " ZERO_EXT"); 190 190 break; 191 + case ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT: 192 + trace_seq_printf(p, " ZAC_MGMT_OUT"); 193 + break; 191 194 } 192 195 break; 193 196 case ATA_CMD_ZAC_MGMT_IN:
+7
include/linux/ata.h
··· 320 320 ATA_SUBCMD_NCQ_NON_DATA_ABORT_QUEUE = 0x00, 321 321 ATA_SUBCMD_NCQ_NON_DATA_SET_FEATURES = 0x05, 322 322 ATA_SUBCMD_NCQ_NON_DATA_ZERO_EXT = 0x06, 323 + ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT = 0x07, 323 324 324 325 /* Subcmds for ATA_CMD_ZAC_MGMT_IN */ 325 326 ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES = 0x00, ··· 334 333 /* READ_LOG_EXT pages */ 335 334 ATA_LOG_DIRECTORY = 0x0, 336 335 ATA_LOG_SATA_NCQ = 0x10, 336 + ATA_LOG_NCQ_NON_DATA = 0x12, 337 337 ATA_LOG_NCQ_SEND_RECV = 0x13, 338 338 ATA_LOG_SATA_ID_DEV_DATA = 0x30, 339 339 ATA_LOG_SATA_SETTINGS = 0x08, ··· 877 875 static inline bool ata_id_has_ncq_send_and_recv(const u16 *id) 878 876 { 879 877 return id[ATA_ID_SATA_CAPABILITY_2] & BIT(6); 878 + } 879 + 880 + static inline bool ata_id_has_ncq_non_data(const u16 *id) 881 + { 882 + return id[ATA_ID_SATA_CAPABILITY_2] & BIT(5); 880 883 } 881 884 882 885 static inline bool ata_id_has_trim(const u16 *id)
+7
include/linux/libata.h
··· 729 729 730 730 /* NCQ send and receive log subcommand support */ 731 731 u8 ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_SIZE]; 732 + u8 ncq_non_data_cmds[ATA_LOG_NCQ_NON_DATA_SIZE]; 732 733 733 734 /* error history */ 734 735 int spdn_cnt; ··· 1657 1656 return (dev->flags & ATA_DFLAG_NCQ_SEND_RECV) && 1658 1657 (dev->ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_ZAC_MGMT_OFFSET] & 1659 1658 ATA_LOG_NCQ_SEND_RECV_ZAC_MGMT_IN_SUPPORTED); 1659 + } 1660 + 1661 + static inline bool ata_fpdma_zac_mgmt_out_supported(struct ata_device *dev) 1662 + { 1663 + return (dev->ncq_non_data_cmds[ATA_LOG_NCQ_NON_DATA_ZAC_MGMT_OFFSET] & 1664 + ATA_LOG_NCQ_NON_DATA_ZAC_MGMT_OUT); 1660 1665 } 1661 1666 1662 1667 static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)