drivetemp.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Hwmon client for disk and solid state drives with temperature sensors
  4. * Copyright (C) 2019 Zodiac Inflight Innovations
  5. *
  6. * With input from:
  7. * Hwmon client for S.M.A.R.T. hard disk drives with temperature sensors.
  8. * (C) 2018 Linus Walleij
  9. *
  10. * hwmon: Driver for SCSI/ATA temperature sensors
  11. * by Constantin Baranov <[email protected]>, submitted September 2009
  12. *
  13. * This drive supports reporting the temperature of SATA drives. It can be
  14. * easily extended to report the temperature of SCSI drives.
  15. *
  16. * The primary means to read drive temperatures and temperature limits
  17. * for ATA drives is the SCT Command Transport feature set as specified in
  18. * ATA8-ACS.
  19. * It can be used to read the current drive temperature, temperature limits,
  20. * and historic minimum and maximum temperatures. The SCT Command Transport
  21. * feature set is documented in "AT Attachment 8 - ATA/ATAPI Command Set
  22. * (ATA8-ACS)".
  23. *
  24. * If the SCT Command Transport feature set is not available, drive temperatures
  25. * may be readable through SMART attributes. Since SMART attributes are not well
  26. * defined, this method is only used as fallback mechanism.
  27. *
  28. * There are three SMART attributes which may report drive temperatures.
  29. * Those are defined as follows (from
  30. * http://www.cropel.com/library/smart-attribute-list.aspx).
  31. *
  32. * 190 Temperature Temperature, monitored by a sensor somewhere inside
  33. * the drive. Raw value typicaly holds the actual
  34. * temperature (hexadecimal) in its rightmost two digits.
  35. *
  36. * 194 Temperature Temperature, monitored by a sensor somewhere inside
  37. * the drive. Raw value typicaly holds the actual
  38. * temperature (hexadecimal) in its rightmost two digits.
  39. *
  40. * 231 Temperature Temperature, monitored by a sensor somewhere inside
  41. * the drive. Raw value typicaly holds the actual
  42. * temperature (hexadecimal) in its rightmost two digits.
  43. *
  44. * Wikipedia defines attributes a bit differently.
  45. *
  46. * 190 Temperature Value is equal to (100-temp. °C), allowing manufacturer
  47. * Difference or to set a minimum threshold which corresponds to a
  48. * Airflow maximum temperature. This also follows the convention of
  49. * Temperature 100 being a best-case value and lower values being
  50. * undesirable. However, some older drives may instead
  51. * report raw Temperature (identical to 0xC2) or
  52. * Temperature minus 50 here.
  53. * 194 Temperature or Indicates the device temperature, if the appropriate
  54. * Temperature sensor is fitted. Lowest byte of the raw value contains
  55. * Celsius the exact temperature value (Celsius degrees).
  56. * 231 Life Left Indicates the approximate SSD life left, in terms of
  57. * (SSDs) or program/erase cycles or available reserved blocks.
  58. * Temperature A normalized value of 100 represents a new drive, with
  59. * a threshold value at 10 indicating a need for
  60. * replacement. A value of 0 may mean that the drive is
  61. * operating in read-only mode to allow data recovery.
  62. * Previously (pre-2010) occasionally used for Drive
  63. * Temperature (more typically reported at 0xC2).
  64. *
  65. * Common denominator is that the first raw byte reports the temperature
  66. * in degrees C on almost all drives. Some drives may report a fractional
  67. * temperature in the second raw byte.
  68. *
  69. * Known exceptions (from libatasmart):
  70. * - SAMSUNG SV0412H and SAMSUNG SV1204H) report the temperature in 10th
  71. * degrees C in the first two raw bytes.
  72. * - A few Maxtor drives report an unknown or bad value in attribute 194.
  73. * - Certain Apple SSD drives report an unknown value in attribute 190.
  74. * Only certain firmware versions are affected.
  75. *
  76. * Those exceptions affect older ATA drives and are currently ignored.
  77. * Also, the second raw byte (possibly reporting the fractional temperature)
  78. * is currently ignored.
  79. *
  80. * Many drives also report temperature limits in additional SMART data raw
  81. * bytes. The format of those is not well defined and varies widely.
  82. * The driver does not currently attempt to report those limits.
  83. *
  84. * According to data in smartmontools, attribute 231 is rarely used to report
  85. * drive temperatures. At the same time, several drives report SSD life left
  86. * in attribute 231, but do not support temperature sensors. For this reason,
  87. * attribute 231 is currently ignored.
  88. *
  89. * Following above definitions, temperatures are reported as follows.
  90. * If SCT Command Transport is supported, it is used to read the
  91. * temperature and, if available, temperature limits.
  92. * - Otherwise, if SMART attribute 194 is supported, it is used to read
  93. * the temperature.
  94. * - Otherwise, if SMART attribute 190 is supported, it is used to read
  95. * the temperature.
  96. */
  97. #include <linux/ata.h>
  98. #include <linux/bits.h>
  99. #include <linux/device.h>
  100. #include <linux/hwmon.h>
  101. #include <linux/kernel.h>
  102. #include <linux/list.h>
  103. #include <linux/module.h>
  104. #include <linux/mutex.h>
  105. #include <scsi/scsi_cmnd.h>
  106. #include <scsi/scsi_device.h>
  107. #include <scsi/scsi_driver.h>
  108. #include <scsi/scsi_proto.h>
  109. struct drivetemp_data {
  110. struct list_head list; /* list of instantiated devices */
  111. struct mutex lock; /* protect data buffer accesses */
  112. struct scsi_device *sdev; /* SCSI device */
  113. struct device *dev; /* instantiating device */
  114. struct device *hwdev; /* hardware monitoring device */
  115. u8 smartdata[ATA_SECT_SIZE]; /* local buffer */
  116. int (*get_temp)(struct drivetemp_data *st, u32 attr, long *val);
  117. bool have_temp_lowest; /* lowest temp in SCT status */
  118. bool have_temp_highest; /* highest temp in SCT status */
  119. bool have_temp_min; /* have min temp */
  120. bool have_temp_max; /* have max temp */
  121. bool have_temp_lcrit; /* have lower critical limit */
  122. bool have_temp_crit; /* have critical limit */
  123. int temp_min; /* min temp */
  124. int temp_max; /* max temp */
  125. int temp_lcrit; /* lower critical limit */
  126. int temp_crit; /* critical limit */
  127. };
  128. static LIST_HEAD(drivetemp_devlist);
  129. #define ATA_MAX_SMART_ATTRS 30
  130. #define SMART_TEMP_PROP_190 190
  131. #define SMART_TEMP_PROP_194 194
  132. #define SCT_STATUS_REQ_ADDR 0xe0
  133. #define SCT_STATUS_VERSION_LOW 0 /* log byte offsets */
  134. #define SCT_STATUS_VERSION_HIGH 1
  135. #define SCT_STATUS_TEMP 200
  136. #define SCT_STATUS_TEMP_LOWEST 201
  137. #define SCT_STATUS_TEMP_HIGHEST 202
  138. #define SCT_READ_LOG_ADDR 0xe1
  139. #define SMART_READ_LOG 0xd5
  140. #define SMART_WRITE_LOG 0xd6
  141. #define INVALID_TEMP 0x80
  142. #define temp_is_valid(temp) ((temp) != INVALID_TEMP)
  143. #define temp_from_sct(temp) (((s8)(temp)) * 1000)
  144. static inline bool ata_id_smart_supported(u16 *id)
  145. {
  146. return id[ATA_ID_COMMAND_SET_1] & BIT(0);
  147. }
  148. static inline bool ata_id_smart_enabled(u16 *id)
  149. {
  150. return id[ATA_ID_CFS_ENABLE_1] & BIT(0);
  151. }
  152. static int drivetemp_scsi_command(struct drivetemp_data *st,
  153. u8 ata_command, u8 feature,
  154. u8 lba_low, u8 lba_mid, u8 lba_high)
  155. {
  156. u8 scsi_cmd[MAX_COMMAND_SIZE];
  157. enum req_op op;
  158. memset(scsi_cmd, 0, sizeof(scsi_cmd));
  159. scsi_cmd[0] = ATA_16;
  160. if (ata_command == ATA_CMD_SMART && feature == SMART_WRITE_LOG) {
  161. scsi_cmd[1] = (5 << 1); /* PIO Data-out */
  162. /*
  163. * No off.line or cc, write to dev, block count in sector count
  164. * field.
  165. */
  166. scsi_cmd[2] = 0x06;
  167. op = REQ_OP_DRV_OUT;
  168. } else {
  169. scsi_cmd[1] = (4 << 1); /* PIO Data-in */
  170. /*
  171. * No off.line or cc, read from dev, block count in sector count
  172. * field.
  173. */
  174. scsi_cmd[2] = 0x0e;
  175. op = REQ_OP_DRV_IN;
  176. }
  177. scsi_cmd[4] = feature;
  178. scsi_cmd[6] = 1; /* 1 sector */
  179. scsi_cmd[8] = lba_low;
  180. scsi_cmd[10] = lba_mid;
  181. scsi_cmd[12] = lba_high;
  182. scsi_cmd[14] = ata_command;
  183. return scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata,
  184. ATA_SECT_SIZE, HZ, 5, NULL);
  185. }
  186. static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature,
  187. u8 select)
  188. {
  189. return drivetemp_scsi_command(st, ATA_CMD_SMART, feature, select,
  190. ATA_SMART_LBAM_PASS, ATA_SMART_LBAH_PASS);
  191. }
  192. static int drivetemp_get_smarttemp(struct drivetemp_data *st, u32 attr,
  193. long *temp)
  194. {
  195. u8 *buf = st->smartdata;
  196. bool have_temp = false;
  197. u8 temp_raw;
  198. u8 csum;
  199. int err;
  200. int i;
  201. err = drivetemp_ata_command(st, ATA_SMART_READ_VALUES, 0);
  202. if (err)
  203. return err;
  204. /* Checksum the read value table */
  205. csum = 0;
  206. for (i = 0; i < ATA_SECT_SIZE; i++)
  207. csum += buf[i];
  208. if (csum) {
  209. dev_dbg(&st->sdev->sdev_gendev,
  210. "checksum error reading SMART values\n");
  211. return -EIO;
  212. }
  213. for (i = 0; i < ATA_MAX_SMART_ATTRS; i++) {
  214. u8 *attr = buf + i * 12;
  215. int id = attr[2];
  216. if (!id)
  217. continue;
  218. if (id == SMART_TEMP_PROP_190) {
  219. temp_raw = attr[7];
  220. have_temp = true;
  221. }
  222. if (id == SMART_TEMP_PROP_194) {
  223. temp_raw = attr[7];
  224. have_temp = true;
  225. break;
  226. }
  227. }
  228. if (have_temp) {
  229. *temp = temp_raw * 1000;
  230. return 0;
  231. }
  232. return -ENXIO;
  233. }
  234. static int drivetemp_get_scttemp(struct drivetemp_data *st, u32 attr, long *val)
  235. {
  236. u8 *buf = st->smartdata;
  237. int err;
  238. err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_STATUS_REQ_ADDR);
  239. if (err)
  240. return err;
  241. switch (attr) {
  242. case hwmon_temp_input:
  243. if (!temp_is_valid(buf[SCT_STATUS_TEMP]))
  244. return -ENODATA;
  245. *val = temp_from_sct(buf[SCT_STATUS_TEMP]);
  246. break;
  247. case hwmon_temp_lowest:
  248. if (!temp_is_valid(buf[SCT_STATUS_TEMP_LOWEST]))
  249. return -ENODATA;
  250. *val = temp_from_sct(buf[SCT_STATUS_TEMP_LOWEST]);
  251. break;
  252. case hwmon_temp_highest:
  253. if (!temp_is_valid(buf[SCT_STATUS_TEMP_HIGHEST]))
  254. return -ENODATA;
  255. *val = temp_from_sct(buf[SCT_STATUS_TEMP_HIGHEST]);
  256. break;
  257. default:
  258. err = -EINVAL;
  259. break;
  260. }
  261. return err;
  262. }
  263. static const char * const sct_avoid_models[] = {
  264. /*
  265. * These drives will have WRITE FPDMA QUEUED command timeouts and sometimes just
  266. * freeze until power-cycled under heavy write loads when their temperature is
  267. * getting polled in SCT mode. The SMART mode seems to be fine, though.
  268. *
  269. * While only the 3 TB model (DT01ACA3) was actually caught exhibiting the
  270. * problem let's play safe here to avoid data corruption and ban the whole
  271. * DT01ACAx family.
  272. * The models from this array are prefix-matched.
  273. */
  274. "TOSHIBA DT01ACA",
  275. };
  276. static bool drivetemp_sct_avoid(struct drivetemp_data *st)
  277. {
  278. struct scsi_device *sdev = st->sdev;
  279. unsigned int ctr;
  280. if (!sdev->model)
  281. return false;
  282. /*
  283. * The "model" field contains just the raw SCSI INQUIRY response
  284. * "product identification" field, which has a width of 16 bytes.
  285. * This field is space-filled, but is NOT NULL-terminated.
  286. */
  287. for (ctr = 0; ctr < ARRAY_SIZE(sct_avoid_models); ctr++)
  288. if (!strncmp(sdev->model, sct_avoid_models[ctr],
  289. strlen(sct_avoid_models[ctr])))
  290. return true;
  291. return false;
  292. }
  293. static int drivetemp_identify_sata(struct drivetemp_data *st)
  294. {
  295. struct scsi_device *sdev = st->sdev;
  296. u8 *buf = st->smartdata;
  297. struct scsi_vpd *vpd;
  298. bool is_ata, is_sata;
  299. bool have_sct_data_table;
  300. bool have_sct_temp;
  301. bool have_smart;
  302. bool have_sct;
  303. u16 *ata_id;
  304. u16 version;
  305. long temp;
  306. int err;
  307. /* SCSI-ATA Translation present? */
  308. rcu_read_lock();
  309. vpd = rcu_dereference(sdev->vpd_pg89);
  310. /*
  311. * Verify that ATA IDENTIFY DEVICE data is included in ATA Information
  312. * VPD and that the drive implements the SATA protocol.
  313. */
  314. if (!vpd || vpd->len < 572 || vpd->data[56] != ATA_CMD_ID_ATA ||
  315. vpd->data[36] != 0x34) {
  316. rcu_read_unlock();
  317. return -ENODEV;
  318. }
  319. ata_id = (u16 *)&vpd->data[60];
  320. is_ata = ata_id_is_ata(ata_id);
  321. is_sata = ata_id_is_sata(ata_id);
  322. have_sct = ata_id_sct_supported(ata_id);
  323. have_sct_data_table = ata_id_sct_data_tables(ata_id);
  324. have_smart = ata_id_smart_supported(ata_id) &&
  325. ata_id_smart_enabled(ata_id);
  326. rcu_read_unlock();
  327. /* bail out if this is not a SATA device */
  328. if (!is_ata || !is_sata)
  329. return -ENODEV;
  330. if (have_sct && drivetemp_sct_avoid(st)) {
  331. dev_notice(&sdev->sdev_gendev,
  332. "will avoid using SCT for temperature monitoring\n");
  333. have_sct = false;
  334. }
  335. if (!have_sct)
  336. goto skip_sct;
  337. err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_STATUS_REQ_ADDR);
  338. if (err)
  339. goto skip_sct;
  340. version = (buf[SCT_STATUS_VERSION_HIGH] << 8) |
  341. buf[SCT_STATUS_VERSION_LOW];
  342. if (version != 2 && version != 3)
  343. goto skip_sct;
  344. have_sct_temp = temp_is_valid(buf[SCT_STATUS_TEMP]);
  345. if (!have_sct_temp)
  346. goto skip_sct;
  347. st->have_temp_lowest = temp_is_valid(buf[SCT_STATUS_TEMP_LOWEST]);
  348. st->have_temp_highest = temp_is_valid(buf[SCT_STATUS_TEMP_HIGHEST]);
  349. if (!have_sct_data_table)
  350. goto skip_sct_data;
  351. /* Request and read temperature history table */
  352. memset(buf, '\0', sizeof(st->smartdata));
  353. buf[0] = 5; /* data table command */
  354. buf[2] = 1; /* read table */
  355. buf[4] = 2; /* temperature history table */
  356. err = drivetemp_ata_command(st, SMART_WRITE_LOG, SCT_STATUS_REQ_ADDR);
  357. if (err)
  358. goto skip_sct_data;
  359. err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_READ_LOG_ADDR);
  360. if (err)
  361. goto skip_sct_data;
  362. /*
  363. * Temperature limits per AT Attachment 8 -
  364. * ATA/ATAPI Command Set (ATA8-ACS)
  365. */
  366. st->have_temp_max = temp_is_valid(buf[6]);
  367. st->have_temp_crit = temp_is_valid(buf[7]);
  368. st->have_temp_min = temp_is_valid(buf[8]);
  369. st->have_temp_lcrit = temp_is_valid(buf[9]);
  370. st->temp_max = temp_from_sct(buf[6]);
  371. st->temp_crit = temp_from_sct(buf[7]);
  372. st->temp_min = temp_from_sct(buf[8]);
  373. st->temp_lcrit = temp_from_sct(buf[9]);
  374. skip_sct_data:
  375. if (have_sct_temp) {
  376. st->get_temp = drivetemp_get_scttemp;
  377. return 0;
  378. }
  379. skip_sct:
  380. if (!have_smart)
  381. return -ENODEV;
  382. st->get_temp = drivetemp_get_smarttemp;
  383. return drivetemp_get_smarttemp(st, hwmon_temp_input, &temp);
  384. }
  385. static int drivetemp_identify(struct drivetemp_data *st)
  386. {
  387. struct scsi_device *sdev = st->sdev;
  388. /* Bail out immediately if there is no inquiry data */
  389. if (!sdev->inquiry || sdev->inquiry_len < 16)
  390. return -ENODEV;
  391. /* Disk device? */
  392. if (sdev->type != TYPE_DISK && sdev->type != TYPE_ZBC)
  393. return -ENODEV;
  394. return drivetemp_identify_sata(st);
  395. }
  396. static int drivetemp_read(struct device *dev, enum hwmon_sensor_types type,
  397. u32 attr, int channel, long *val)
  398. {
  399. struct drivetemp_data *st = dev_get_drvdata(dev);
  400. int err = 0;
  401. if (type != hwmon_temp)
  402. return -EINVAL;
  403. switch (attr) {
  404. case hwmon_temp_input:
  405. case hwmon_temp_lowest:
  406. case hwmon_temp_highest:
  407. mutex_lock(&st->lock);
  408. err = st->get_temp(st, attr, val);
  409. mutex_unlock(&st->lock);
  410. break;
  411. case hwmon_temp_lcrit:
  412. *val = st->temp_lcrit;
  413. break;
  414. case hwmon_temp_min:
  415. *val = st->temp_min;
  416. break;
  417. case hwmon_temp_max:
  418. *val = st->temp_max;
  419. break;
  420. case hwmon_temp_crit:
  421. *val = st->temp_crit;
  422. break;
  423. default:
  424. err = -EINVAL;
  425. break;
  426. }
  427. return err;
  428. }
  429. static umode_t drivetemp_is_visible(const void *data,
  430. enum hwmon_sensor_types type,
  431. u32 attr, int channel)
  432. {
  433. const struct drivetemp_data *st = data;
  434. switch (type) {
  435. case hwmon_temp:
  436. switch (attr) {
  437. case hwmon_temp_input:
  438. return 0444;
  439. case hwmon_temp_lowest:
  440. if (st->have_temp_lowest)
  441. return 0444;
  442. break;
  443. case hwmon_temp_highest:
  444. if (st->have_temp_highest)
  445. return 0444;
  446. break;
  447. case hwmon_temp_min:
  448. if (st->have_temp_min)
  449. return 0444;
  450. break;
  451. case hwmon_temp_max:
  452. if (st->have_temp_max)
  453. return 0444;
  454. break;
  455. case hwmon_temp_lcrit:
  456. if (st->have_temp_lcrit)
  457. return 0444;
  458. break;
  459. case hwmon_temp_crit:
  460. if (st->have_temp_crit)
  461. return 0444;
  462. break;
  463. default:
  464. break;
  465. }
  466. break;
  467. default:
  468. break;
  469. }
  470. return 0;
  471. }
  472. static const struct hwmon_channel_info *drivetemp_info[] = {
  473. HWMON_CHANNEL_INFO(chip,
  474. HWMON_C_REGISTER_TZ),
  475. HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT |
  476. HWMON_T_LOWEST | HWMON_T_HIGHEST |
  477. HWMON_T_MIN | HWMON_T_MAX |
  478. HWMON_T_LCRIT | HWMON_T_CRIT),
  479. NULL
  480. };
  481. static const struct hwmon_ops drivetemp_ops = {
  482. .is_visible = drivetemp_is_visible,
  483. .read = drivetemp_read,
  484. };
  485. static const struct hwmon_chip_info drivetemp_chip_info = {
  486. .ops = &drivetemp_ops,
  487. .info = drivetemp_info,
  488. };
  489. /*
  490. * The device argument points to sdev->sdev_dev. Its parent is
  491. * sdev->sdev_gendev, which we can use to get the scsi_device pointer.
  492. */
  493. static int drivetemp_add(struct device *dev, struct class_interface *intf)
  494. {
  495. struct scsi_device *sdev = to_scsi_device(dev->parent);
  496. struct drivetemp_data *st;
  497. int err;
  498. st = kzalloc(sizeof(*st), GFP_KERNEL);
  499. if (!st)
  500. return -ENOMEM;
  501. st->sdev = sdev;
  502. st->dev = dev;
  503. mutex_init(&st->lock);
  504. if (drivetemp_identify(st)) {
  505. err = -ENODEV;
  506. goto abort;
  507. }
  508. st->hwdev = hwmon_device_register_with_info(dev->parent, "drivetemp",
  509. st, &drivetemp_chip_info,
  510. NULL);
  511. if (IS_ERR(st->hwdev)) {
  512. err = PTR_ERR(st->hwdev);
  513. goto abort;
  514. }
  515. list_add(&st->list, &drivetemp_devlist);
  516. return 0;
  517. abort:
  518. kfree(st);
  519. return err;
  520. }
  521. static void drivetemp_remove(struct device *dev, struct class_interface *intf)
  522. {
  523. struct drivetemp_data *st, *tmp;
  524. list_for_each_entry_safe(st, tmp, &drivetemp_devlist, list) {
  525. if (st->dev == dev) {
  526. list_del(&st->list);
  527. hwmon_device_unregister(st->hwdev);
  528. kfree(st);
  529. break;
  530. }
  531. }
  532. }
  533. static struct class_interface drivetemp_interface = {
  534. .add_dev = drivetemp_add,
  535. .remove_dev = drivetemp_remove,
  536. };
  537. static int __init drivetemp_init(void)
  538. {
  539. return scsi_register_interface(&drivetemp_interface);
  540. }
  541. static void __exit drivetemp_exit(void)
  542. {
  543. scsi_unregister_interface(&drivetemp_interface);
  544. }
  545. module_init(drivetemp_init);
  546. module_exit(drivetemp_exit);
  547. MODULE_AUTHOR("Guenter Roeck <[email protected]>");
  548. MODULE_DESCRIPTION("Hard drive temperature monitor");
  549. MODULE_LICENSE("GPL");
  550. MODULE_ALIAS("platform:drivetemp");