diff options
Diffstat (limited to 'drivers/ata/ahci.c')
| -rw-r--r-- | drivers/ata/ahci.c | 331 |
1 files changed, 325 insertions, 6 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5e6468a7ca4b..dc7596f028b6 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -56,6 +56,12 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip) | |||
| 56 | static int ahci_enable_alpm(struct ata_port *ap, | 56 | static int ahci_enable_alpm(struct ata_port *ap, |
| 57 | enum link_pm policy); | 57 | enum link_pm policy); |
| 58 | static void ahci_disable_alpm(struct ata_port *ap); | 58 | static void ahci_disable_alpm(struct ata_port *ap); |
| 59 | static ssize_t ahci_led_show(struct ata_port *ap, char *buf); | ||
| 60 | static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, | ||
| 61 | size_t size); | ||
| 62 | static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, | ||
| 63 | ssize_t size); | ||
| 64 | #define MAX_SLOTS 8 | ||
| 59 | 65 | ||
| 60 | enum { | 66 | enum { |
| 61 | AHCI_PCI_BAR = 5, | 67 | AHCI_PCI_BAR = 5, |
| @@ -98,6 +104,8 @@ enum { | |||
| 98 | HOST_IRQ_STAT = 0x08, /* interrupt status */ | 104 | HOST_IRQ_STAT = 0x08, /* interrupt status */ |
| 99 | HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */ | 105 | HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */ |
| 100 | HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ | 106 | HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ |
| 107 | HOST_EM_LOC = 0x1c, /* Enclosure Management location */ | ||
| 108 | HOST_EM_CTL = 0x20, /* Enclosure Management Control */ | ||
| 101 | 109 | ||
| 102 | /* HOST_CTL bits */ | 110 | /* HOST_CTL bits */ |
| 103 | HOST_RESET = (1 << 0), /* reset controller; self-clear */ | 111 | HOST_RESET = (1 << 0), /* reset controller; self-clear */ |
| @@ -105,6 +113,7 @@ enum { | |||
| 105 | HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ | 113 | HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ |
| 106 | 114 | ||
| 107 | /* HOST_CAP bits */ | 115 | /* HOST_CAP bits */ |
| 116 | HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ | ||
| 108 | HOST_CAP_SSC = (1 << 14), /* Slumber capable */ | 117 | HOST_CAP_SSC = (1 << 14), /* Slumber capable */ |
| 109 | HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ | 118 | HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ |
| 110 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ | 119 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ |
| @@ -202,6 +211,11 @@ enum { | |||
| 202 | ATA_FLAG_IPM, | 211 | ATA_FLAG_IPM, |
| 203 | 212 | ||
| 204 | ICH_MAP = 0x90, /* ICH MAP register */ | 213 | ICH_MAP = 0x90, /* ICH MAP register */ |
| 214 | |||
| 215 | /* em_ctl bits */ | ||
| 216 | EM_CTL_RST = (1 << 9), /* Reset */ | ||
| 217 | EM_CTL_TM = (1 << 8), /* Transmit Message */ | ||
| 218 | EM_CTL_ALHD = (1 << 26), /* Activity LED */ | ||
| 205 | }; | 219 | }; |
| 206 | 220 | ||
| 207 | struct ahci_cmd_hdr { | 221 | struct ahci_cmd_hdr { |
| @@ -219,12 +233,21 @@ struct ahci_sg { | |||
| 219 | __le32 flags_size; | 233 | __le32 flags_size; |
| 220 | }; | 234 | }; |
| 221 | 235 | ||
| 236 | struct ahci_em_priv { | ||
| 237 | enum sw_activity blink_policy; | ||
| 238 | struct timer_list timer; | ||
| 239 | unsigned long saved_activity; | ||
| 240 | unsigned long activity; | ||
| 241 | unsigned long led_state; | ||
| 242 | }; | ||
| 243 | |||
| 222 | struct ahci_host_priv { | 244 | struct ahci_host_priv { |
| 223 | unsigned int flags; /* AHCI_HFLAG_* */ | 245 | unsigned int flags; /* AHCI_HFLAG_* */ |
| 224 | u32 cap; /* cap to use */ | 246 | u32 cap; /* cap to use */ |
| 225 | u32 port_map; /* port map to use */ | 247 | u32 port_map; /* port map to use */ |
| 226 | u32 saved_cap; /* saved initial cap */ | 248 | u32 saved_cap; /* saved initial cap */ |
| 227 | u32 saved_port_map; /* saved initial port_map */ | 249 | u32 saved_port_map; /* saved initial port_map */ |
| 250 | u32 em_loc; /* enclosure management location */ | ||
| 228 | }; | 251 | }; |
| 229 | 252 | ||
| 230 | struct ahci_port_priv { | 253 | struct ahci_port_priv { |
| @@ -240,6 +263,8 @@ struct ahci_port_priv { | |||
| 240 | unsigned int ncq_saw_dmas:1; | 263 | unsigned int ncq_saw_dmas:1; |
| 241 | unsigned int ncq_saw_sdb:1; | 264 | unsigned int ncq_saw_sdb:1; |
| 242 | u32 intr_mask; /* interrupts to enable */ | 265 | u32 intr_mask; /* interrupts to enable */ |
| 266 | struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info | ||
| 267 | * per PM slot */ | ||
| 243 | }; | 268 | }; |
| 244 | 269 | ||
| 245 | static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); | 270 | static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); |
| @@ -277,9 +302,20 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); | |||
| 277 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); | 302 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); |
| 278 | static int ahci_pci_device_resume(struct pci_dev *pdev); | 303 | static int ahci_pci_device_resume(struct pci_dev *pdev); |
| 279 | #endif | 304 | #endif |
| 305 | static ssize_t ahci_activity_show(struct ata_device *dev, char *buf); | ||
| 306 | static ssize_t ahci_activity_store(struct ata_device *dev, | ||
| 307 | enum sw_activity val); | ||
| 308 | static void ahci_init_sw_activity(struct ata_link *link); | ||
| 280 | 309 | ||
| 281 | static struct device_attribute *ahci_shost_attrs[] = { | 310 | static struct device_attribute *ahci_shost_attrs[] = { |
| 282 | &dev_attr_link_power_management_policy, | 311 | &dev_attr_link_power_management_policy, |
| 312 | &dev_attr_em_message_type, | ||
| 313 | &dev_attr_em_message, | ||
| 314 | NULL | ||
| 315 | }; | ||
| 316 | |||
| 317 | static struct device_attribute *ahci_sdev_attrs[] = { | ||
| 318 | &dev_attr_sw_activity, | ||
| 283 | NULL | 319 | NULL |
| 284 | }; | 320 | }; |
| 285 | 321 | ||
| @@ -289,6 +325,7 @@ static struct scsi_host_template ahci_sht = { | |||
| 289 | .sg_tablesize = AHCI_MAX_SG, | 325 | .sg_tablesize = AHCI_MAX_SG, |
| 290 | .dma_boundary = AHCI_DMA_BOUNDARY, | 326 | .dma_boundary = AHCI_DMA_BOUNDARY, |
| 291 | .shost_attrs = ahci_shost_attrs, | 327 | .shost_attrs = ahci_shost_attrs, |
| 328 | .sdev_attrs = ahci_sdev_attrs, | ||
| 292 | }; | 329 | }; |
| 293 | 330 | ||
| 294 | static struct ata_port_operations ahci_ops = { | 331 | static struct ata_port_operations ahci_ops = { |
| @@ -316,6 +353,10 @@ static struct ata_port_operations ahci_ops = { | |||
| 316 | 353 | ||
| 317 | .enable_pm = ahci_enable_alpm, | 354 | .enable_pm = ahci_enable_alpm, |
| 318 | .disable_pm = ahci_disable_alpm, | 355 | .disable_pm = ahci_disable_alpm, |
| 356 | .em_show = ahci_led_show, | ||
| 357 | .em_store = ahci_led_store, | ||
| 358 | .sw_activity_show = ahci_activity_show, | ||
| 359 | .sw_activity_store = ahci_activity_store, | ||
| 319 | #ifdef CONFIG_PM | 360 | #ifdef CONFIG_PM |
| 320 | .port_suspend = ahci_port_suspend, | 361 | .port_suspend = ahci_port_suspend, |
| 321 | .port_resume = ahci_port_resume, | 362 | .port_resume = ahci_port_resume, |
| @@ -561,6 +602,11 @@ static struct pci_driver ahci_pci_driver = { | |||
| 561 | #endif | 602 | #endif |
| 562 | }; | 603 | }; |
| 563 | 604 | ||
| 605 | static int ahci_em_messages = 1; | ||
| 606 | module_param(ahci_em_messages, int, 0444); | ||
| 607 | /* add other LED protocol types when they become supported */ | ||
| 608 | MODULE_PARM_DESC(ahci_em_messages, | ||
| 609 | "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED"); | ||
| 564 | 610 | ||
| 565 | static inline int ahci_nr_ports(u32 cap) | 611 | static inline int ahci_nr_ports(u32 cap) |
| 566 | { | 612 | { |
| @@ -1031,11 +1077,28 @@ static void ahci_power_down(struct ata_port *ap) | |||
| 1031 | 1077 | ||
| 1032 | static void ahci_start_port(struct ata_port *ap) | 1078 | static void ahci_start_port(struct ata_port *ap) |
| 1033 | { | 1079 | { |
| 1080 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1081 | struct ata_link *link; | ||
| 1082 | struct ahci_em_priv *emp; | ||
| 1083 | |||
| 1034 | /* enable FIS reception */ | 1084 | /* enable FIS reception */ |
| 1035 | ahci_start_fis_rx(ap); | 1085 | ahci_start_fis_rx(ap); |
| 1036 | 1086 | ||
| 1037 | /* enable DMA */ | 1087 | /* enable DMA */ |
| 1038 | ahci_start_engine(ap); | 1088 | ahci_start_engine(ap); |
| 1089 | |||
| 1090 | /* turn on LEDs */ | ||
| 1091 | if (ap->flags & ATA_FLAG_EM) { | ||
| 1092 | ata_port_for_each_link(link, ap) { | ||
| 1093 | emp = &pp->em_priv[link->pmp]; | ||
| 1094 | ahci_transmit_led_message(ap, emp->led_state, 4); | ||
| 1095 | } | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (ap->flags & ATA_FLAG_SW_ACTIVITY) | ||
| 1099 | ata_port_for_each_link(link, ap) | ||
| 1100 | ahci_init_sw_activity(link); | ||
| 1101 | |||
| 1039 | } | 1102 | } |
| 1040 | 1103 | ||
| 1041 | static int ahci_deinit_port(struct ata_port *ap, const char **emsg) | 1104 | static int ahci_deinit_port(struct ata_port *ap, const char **emsg) |
| @@ -1079,12 +1142,15 @@ static int ahci_reset_controller(struct ata_host *host) | |||
| 1079 | readl(mmio + HOST_CTL); /* flush */ | 1142 | readl(mmio + HOST_CTL); /* flush */ |
| 1080 | } | 1143 | } |
| 1081 | 1144 | ||
| 1082 | /* reset must complete within 1 second, or | 1145 | /* |
| 1146 | * to perform host reset, OS should set HOST_RESET | ||
| 1147 | * and poll until this bit is read to be "0". | ||
| 1148 | * reset must complete within 1 second, or | ||
| 1083 | * the hardware should be considered fried. | 1149 | * the hardware should be considered fried. |
| 1084 | */ | 1150 | */ |
| 1085 | ssleep(1); | 1151 | tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET, |
| 1152 | HOST_RESET, 10, 1000); | ||
| 1086 | 1153 | ||
| 1087 | tmp = readl(mmio + HOST_CTL); | ||
| 1088 | if (tmp & HOST_RESET) { | 1154 | if (tmp & HOST_RESET) { |
| 1089 | dev_printk(KERN_ERR, host->dev, | 1155 | dev_printk(KERN_ERR, host->dev, |
| 1090 | "controller reset failed (0x%x)\n", tmp); | 1156 | "controller reset failed (0x%x)\n", tmp); |
| @@ -1116,6 +1182,230 @@ static int ahci_reset_controller(struct ata_host *host) | |||
| 1116 | return 0; | 1182 | return 0; |
| 1117 | } | 1183 | } |
| 1118 | 1184 | ||
| 1185 | static void ahci_sw_activity(struct ata_link *link) | ||
| 1186 | { | ||
| 1187 | struct ata_port *ap = link->ap; | ||
| 1188 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1189 | struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; | ||
| 1190 | |||
| 1191 | if (!(link->flags & ATA_LFLAG_SW_ACTIVITY)) | ||
| 1192 | return; | ||
| 1193 | |||
| 1194 | emp->activity++; | ||
| 1195 | if (!timer_pending(&emp->timer)) | ||
| 1196 | mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10)); | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | static void ahci_sw_activity_blink(unsigned long arg) | ||
| 1200 | { | ||
| 1201 | struct ata_link *link = (struct ata_link *)arg; | ||
| 1202 | struct ata_port *ap = link->ap; | ||
| 1203 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1204 | struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; | ||
| 1205 | unsigned long led_message = emp->led_state; | ||
| 1206 | u32 activity_led_state; | ||
| 1207 | |||
| 1208 | led_message &= 0xffff0000; | ||
| 1209 | led_message |= ap->port_no | (link->pmp << 8); | ||
| 1210 | |||
| 1211 | /* check to see if we've had activity. If so, | ||
| 1212 | * toggle state of LED and reset timer. If not, | ||
| 1213 | * turn LED to desired idle state. | ||
| 1214 | */ | ||
| 1215 | if (emp->saved_activity != emp->activity) { | ||
| 1216 | emp->saved_activity = emp->activity; | ||
| 1217 | /* get the current LED state */ | ||
| 1218 | activity_led_state = led_message & 0x00010000; | ||
| 1219 | |||
| 1220 | if (activity_led_state) | ||
| 1221 | activity_led_state = 0; | ||
| 1222 | else | ||
| 1223 | activity_led_state = 1; | ||
| 1224 | |||
| 1225 | /* clear old state */ | ||
| 1226 | led_message &= 0xfff8ffff; | ||
| 1227 | |||
| 1228 | /* toggle state */ | ||
| 1229 | led_message |= (activity_led_state << 16); | ||
| 1230 | mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100)); | ||
| 1231 | } else { | ||
| 1232 | /* switch to idle */ | ||
| 1233 | led_message &= 0xfff8ffff; | ||
| 1234 | if (emp->blink_policy == BLINK_OFF) | ||
| 1235 | led_message |= (1 << 16); | ||
| 1236 | } | ||
| 1237 | ahci_transmit_led_message(ap, led_message, 4); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | static void ahci_init_sw_activity(struct ata_link *link) | ||
| 1241 | { | ||
| 1242 | struct ata_port *ap = link->ap; | ||
| 1243 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1244 | struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; | ||
| 1245 | |||
| 1246 | /* init activity stats, setup timer */ | ||
| 1247 | emp->saved_activity = emp->activity = 0; | ||
| 1248 | setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link); | ||
| 1249 | |||
| 1250 | /* check our blink policy and set flag for link if it's enabled */ | ||
| 1251 | if (emp->blink_policy) | ||
| 1252 | link->flags |= ATA_LFLAG_SW_ACTIVITY; | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | static int ahci_reset_em(struct ata_host *host) | ||
| 1256 | { | ||
| 1257 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | ||
| 1258 | u32 em_ctl; | ||
| 1259 | |||
| 1260 | em_ctl = readl(mmio + HOST_EM_CTL); | ||
| 1261 | if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST)) | ||
| 1262 | return -EINVAL; | ||
| 1263 | |||
| 1264 | writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL); | ||
| 1265 | return 0; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, | ||
| 1269 | ssize_t size) | ||
| 1270 | { | ||
| 1271 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
| 1272 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1273 | void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; | ||
| 1274 | u32 em_ctl; | ||
| 1275 | u32 message[] = {0, 0}; | ||
| 1276 | unsigned int flags; | ||
| 1277 | int pmp; | ||
| 1278 | struct ahci_em_priv *emp; | ||
| 1279 | |||
| 1280 | /* get the slot number from the message */ | ||
| 1281 | pmp = (state & 0x0000ff00) >> 8; | ||
| 1282 | if (pmp < MAX_SLOTS) | ||
| 1283 | emp = &pp->em_priv[pmp]; | ||
| 1284 | else | ||
| 1285 | return -EINVAL; | ||
| 1286 | |||
| 1287 | spin_lock_irqsave(ap->lock, flags); | ||
| 1288 | |||
| 1289 | /* | ||
| 1290 | * if we are still busy transmitting a previous message, | ||
| 1291 | * do not allow | ||
| 1292 | */ | ||
| 1293 | em_ctl = readl(mmio + HOST_EM_CTL); | ||
| 1294 | if (em_ctl & EM_CTL_TM) { | ||
| 1295 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 1296 | return -EINVAL; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | /* | ||
| 1300 | * create message header - this is all zero except for | ||
| 1301 | * the message size, which is 4 bytes. | ||
| 1302 | */ | ||
| 1303 | message[0] |= (4 << 8); | ||
| 1304 | |||
| 1305 | /* ignore 0:4 of byte zero, fill in port info yourself */ | ||
| 1306 | message[1] = ((state & 0xfffffff0) | ap->port_no); | ||
| 1307 | |||
| 1308 | /* write message to EM_LOC */ | ||
| 1309 | writel(message[0], mmio + hpriv->em_loc); | ||
| 1310 | writel(message[1], mmio + hpriv->em_loc+4); | ||
| 1311 | |||
| 1312 | /* save off new led state for port/slot */ | ||
| 1313 | emp->led_state = message[1]; | ||
| 1314 | |||
| 1315 | /* | ||
| 1316 | * tell hardware to transmit the message | ||
| 1317 | */ | ||
| 1318 | writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL); | ||
| 1319 | |||
| 1320 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 1321 | return size; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static ssize_t ahci_led_show(struct ata_port *ap, char *buf) | ||
| 1325 | { | ||
| 1326 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1327 | struct ata_link *link; | ||
| 1328 | struct ahci_em_priv *emp; | ||
| 1329 | int rc = 0; | ||
| 1330 | |||
| 1331 | ata_port_for_each_link(link, ap) { | ||
| 1332 | emp = &pp->em_priv[link->pmp]; | ||
| 1333 | rc += sprintf(buf, "%lx\n", emp->led_state); | ||
| 1334 | } | ||
| 1335 | return rc; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, | ||
| 1339 | size_t size) | ||
| 1340 | { | ||
| 1341 | int state; | ||
| 1342 | int pmp; | ||
| 1343 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1344 | struct ahci_em_priv *emp; | ||
| 1345 | |||
| 1346 | state = simple_strtoul(buf, NULL, 0); | ||
| 1347 | |||
| 1348 | /* get the slot number from the message */ | ||
| 1349 | pmp = (state & 0x0000ff00) >> 8; | ||
| 1350 | if (pmp < MAX_SLOTS) | ||
| 1351 | emp = &pp->em_priv[pmp]; | ||
| 1352 | else | ||
| 1353 | return -EINVAL; | ||
| 1354 | |||
| 1355 | /* mask off the activity bits if we are in sw_activity | ||
| 1356 | * mode, user should turn off sw_activity before setting | ||
| 1357 | * activity led through em_message | ||
| 1358 | */ | ||
| 1359 | if (emp->blink_policy) | ||
| 1360 | state &= 0xfff8ffff; | ||
| 1361 | |||
| 1362 | return ahci_transmit_led_message(ap, state, size); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val) | ||
| 1366 | { | ||
| 1367 | struct ata_link *link = dev->link; | ||
| 1368 | struct ata_port *ap = link->ap; | ||
| 1369 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1370 | struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; | ||
| 1371 | u32 port_led_state = emp->led_state; | ||
| 1372 | |||
| 1373 | /* save the desired Activity LED behavior */ | ||
| 1374 | if (val == OFF) { | ||
| 1375 | /* clear LFLAG */ | ||
| 1376 | link->flags &= ~(ATA_LFLAG_SW_ACTIVITY); | ||
| 1377 | |||
| 1378 | /* set the LED to OFF */ | ||
| 1379 | port_led_state &= 0xfff80000; | ||
| 1380 | port_led_state |= (ap->port_no | (link->pmp << 8)); | ||
| 1381 | ahci_transmit_led_message(ap, port_led_state, 4); | ||
| 1382 | } else { | ||
| 1383 | link->flags |= ATA_LFLAG_SW_ACTIVITY; | ||
| 1384 | if (val == BLINK_OFF) { | ||
| 1385 | /* set LED to ON for idle */ | ||
| 1386 | port_led_state &= 0xfff80000; | ||
| 1387 | port_led_state |= (ap->port_no | (link->pmp << 8)); | ||
| 1388 | port_led_state |= 0x00010000; /* check this */ | ||
| 1389 | ahci_transmit_led_message(ap, port_led_state, 4); | ||
| 1390 | } | ||
| 1391 | } | ||
| 1392 | emp->blink_policy = val; | ||
| 1393 | return 0; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | static ssize_t ahci_activity_show(struct ata_device *dev, char *buf) | ||
| 1397 | { | ||
| 1398 | struct ata_link *link = dev->link; | ||
| 1399 | struct ata_port *ap = link->ap; | ||
| 1400 | struct ahci_port_priv *pp = ap->private_data; | ||
| 1401 | struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; | ||
| 1402 | |||
| 1403 | /* display the saved value of activity behavior for this | ||
| 1404 | * disk. | ||
| 1405 | */ | ||
| 1406 | return sprintf(buf, "%d\n", emp->blink_policy); | ||
| 1407 | } | ||
| 1408 | |||
| 1119 | static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap, | 1409 | static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap, |
| 1120 | int port_no, void __iomem *mmio, | 1410 | int port_no, void __iomem *mmio, |
| 1121 | void __iomem *port_mmio) | 1411 | void __iomem *port_mmio) |
| @@ -1846,7 +2136,8 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | |||
| 1846 | if (qc->tf.protocol == ATA_PROT_NCQ) | 2136 | if (qc->tf.protocol == ATA_PROT_NCQ) |
| 1847 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); | 2137 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); |
| 1848 | writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); | 2138 | writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); |
| 1849 | readl(port_mmio + PORT_CMD_ISSUE); /* flush */ | 2139 | |
| 2140 | ahci_sw_activity(qc->dev->link); | ||
| 1850 | 2141 | ||
| 1851 | return 0; | 2142 | return 0; |
| 1852 | } | 2143 | } |
| @@ -2154,7 +2445,8 @@ static void ahci_print_info(struct ata_host *host) | |||
| 2154 | dev_printk(KERN_INFO, &pdev->dev, | 2445 | dev_printk(KERN_INFO, &pdev->dev, |
| 2155 | "flags: " | 2446 | "flags: " |
| 2156 | "%s%s%s%s%s%s%s" | 2447 | "%s%s%s%s%s%s%s" |
| 2157 | "%s%s%s%s%s%s%s\n" | 2448 | "%s%s%s%s%s%s%s" |
| 2449 | "%s\n" | ||
| 2158 | , | 2450 | , |
| 2159 | 2451 | ||
| 2160 | cap & (1 << 31) ? "64bit " : "", | 2452 | cap & (1 << 31) ? "64bit " : "", |
| @@ -2171,7 +2463,8 @@ static void ahci_print_info(struct ata_host *host) | |||
| 2171 | cap & (1 << 17) ? "pmp " : "", | 2463 | cap & (1 << 17) ? "pmp " : "", |
| 2172 | cap & (1 << 15) ? "pio " : "", | 2464 | cap & (1 << 15) ? "pio " : "", |
| 2173 | cap & (1 << 14) ? "slum " : "", | 2465 | cap & (1 << 14) ? "slum " : "", |
| 2174 | cap & (1 << 13) ? "part " : "" | 2466 | cap & (1 << 13) ? "part " : "", |
| 2467 | cap & (1 << 6) ? "ems ": "" | ||
| 2175 | ); | 2468 | ); |
| 2176 | } | 2469 | } |
| 2177 | 2470 | ||
| @@ -2291,6 +2584,24 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2291 | if (hpriv->cap & HOST_CAP_PMP) | 2584 | if (hpriv->cap & HOST_CAP_PMP) |
| 2292 | pi.flags |= ATA_FLAG_PMP; | 2585 | pi.flags |= ATA_FLAG_PMP; |
| 2293 | 2586 | ||
| 2587 | if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) { | ||
| 2588 | u8 messages; | ||
| 2589 | void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; | ||
| 2590 | u32 em_loc = readl(mmio + HOST_EM_LOC); | ||
| 2591 | u32 em_ctl = readl(mmio + HOST_EM_CTL); | ||
| 2592 | |||
| 2593 | messages = (em_ctl & 0x000f0000) >> 16; | ||
| 2594 | |||
| 2595 | /* we only support LED message type right now */ | ||
| 2596 | if ((messages & 0x01) && (ahci_em_messages == 1)) { | ||
| 2597 | /* store em_loc */ | ||
| 2598 | hpriv->em_loc = ((em_loc >> 16) * 4); | ||
| 2599 | pi.flags |= ATA_FLAG_EM; | ||
| 2600 | if (!(em_ctl & EM_CTL_ALHD)) | ||
| 2601 | pi.flags |= ATA_FLAG_SW_ACTIVITY; | ||
| 2602 | } | ||
| 2603 | } | ||
| 2604 | |||
| 2294 | /* CAP.NP sometimes indicate the index of the last enabled | 2605 | /* CAP.NP sometimes indicate the index of the last enabled |
| 2295 | * port, at other times, that of the last possible port, so | 2606 | * port, at other times, that of the last possible port, so |
| 2296 | * determining the maximum port number requires looking at | 2607 | * determining the maximum port number requires looking at |
| @@ -2304,6 +2615,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2304 | host->iomap = pcim_iomap_table(pdev); | 2615 | host->iomap = pcim_iomap_table(pdev); |
| 2305 | host->private_data = hpriv; | 2616 | host->private_data = hpriv; |
| 2306 | 2617 | ||
| 2618 | if (pi.flags & ATA_FLAG_EM) | ||
| 2619 | ahci_reset_em(host); | ||
| 2620 | |||
| 2307 | for (i = 0; i < host->n_ports; i++) { | 2621 | for (i = 0; i < host->n_ports; i++) { |
| 2308 | struct ata_port *ap = host->ports[i]; | 2622 | struct ata_port *ap = host->ports[i]; |
| 2309 | 2623 | ||
| @@ -2314,6 +2628,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2314 | /* set initial link pm policy */ | 2628 | /* set initial link pm policy */ |
| 2315 | ap->pm_policy = NOT_AVAILABLE; | 2629 | ap->pm_policy = NOT_AVAILABLE; |
| 2316 | 2630 | ||
| 2631 | /* set enclosure management message type */ | ||
| 2632 | if (ap->flags & ATA_FLAG_EM) | ||
| 2633 | ap->em_message_type = ahci_em_messages; | ||
| 2634 | |||
| 2635 | |||
| 2317 | /* disabled/not-implemented port */ | 2636 | /* disabled/not-implemented port */ |
| 2318 | if (!(hpriv->port_map & (1 << i))) | 2637 | if (!(hpriv->port_map & (1 << i))) |
| 2319 | ap->ops = &ata_dummy_port_ops; | 2638 | ap->ops = &ata_dummy_port_ops; |
