aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2017-02-22 15:32:36 -0500
committerJens Axboe <axboe@fb.com>2017-02-22 15:34:00 -0500
commitbd4da3abaabffdd2472fb7085fcadd5d1d8c2153 (patch)
treeccae778d88397594827cf6f146dfb8ca7ace189b
parente5a39dd8238e5d42c830bbd8d31211adf6fea6ca (diff)
nvme: Add a quirk mechanism that uses identify_ctrl
Currently, all NVMe quirks are based on PCI IDs. Add a mechanism to define quirks based on identify_ctrl's vendor id, model number, and/or firmware revision. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/nvme/host/core.c64
-rw-r--r--drivers/nvme/host/nvme.h1
2 files changed, 65 insertions, 0 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 8b1be128b66e..38efe4f752a1 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1252,6 +1252,50 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
1252 blk_queue_write_cache(q, vwc, vwc); 1252 blk_queue_write_cache(q, vwc, vwc);
1253} 1253}
1254 1254
1255struct nvme_core_quirk_entry {
1256 /*
1257 * NVMe model and firmware strings are padded with spaces. For
1258 * simplicity, strings in the quirk table are padded with NULLs
1259 * instead.
1260 */
1261 u16 vid;
1262 const char *mn;
1263 const char *fr;
1264 unsigned long quirks;
1265};
1266
1267static const struct nvme_core_quirk_entry core_quirks[] = {
1268};
1269
1270/* match is null-terminated but idstr is space-padded. */
1271static bool string_matches(const char *idstr, const char *match, size_t len)
1272{
1273 size_t matchlen;
1274
1275 if (!match)
1276 return true;
1277
1278 matchlen = strlen(match);
1279 WARN_ON_ONCE(matchlen > len);
1280
1281 if (memcmp(idstr, match, matchlen))
1282 return false;
1283
1284 for (; matchlen < len; matchlen++)
1285 if (idstr[matchlen] != ' ')
1286 return false;
1287
1288 return true;
1289}
1290
1291static bool quirk_matches(const struct nvme_id_ctrl *id,
1292 const struct nvme_core_quirk_entry *q)
1293{
1294 return q->vid == le16_to_cpu(id->vid) &&
1295 string_matches(id->mn, q->mn, sizeof(id->mn)) &&
1296 string_matches(id->fr, q->fr, sizeof(id->fr));
1297}
1298
1255/* 1299/*
1256 * Initialize the cached copies of the Identify data and various controller 1300 * Initialize the cached copies of the Identify data and various controller
1257 * register in our nvme_ctrl structure. This should be called as soon as 1301 * register in our nvme_ctrl structure. This should be called as soon as
@@ -1286,6 +1330,24 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
1286 return -EIO; 1330 return -EIO;
1287 } 1331 }
1288 1332
1333 if (!ctrl->identified) {
1334 /*
1335 * Check for quirks. Quirk can depend on firmware version,
1336 * so, in principle, the set of quirks present can change
1337 * across a reset. As a possible future enhancement, we
1338 * could re-scan for quirks every time we reinitialize
1339 * the device, but we'd have to make sure that the driver
1340 * behaves intelligently if the quirks change.
1341 */
1342
1343 int i;
1344
1345 for (i = 0; i < ARRAY_SIZE(core_quirks); i++) {
1346 if (quirk_matches(id, &core_quirks[i]))
1347 ctrl->quirks |= core_quirks[i].quirks;
1348 }
1349 }
1350
1289 ctrl->oacs = le16_to_cpu(id->oacs); 1351 ctrl->oacs = le16_to_cpu(id->oacs);
1290 ctrl->vid = le16_to_cpu(id->vid); 1352 ctrl->vid = le16_to_cpu(id->vid);
1291 ctrl->oncs = le16_to_cpup(&id->oncs); 1353 ctrl->oncs = le16_to_cpup(&id->oncs);
@@ -1329,6 +1391,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
1329 } 1391 }
1330 1392
1331 kfree(id); 1393 kfree(id);
1394
1395 ctrl->identified = true;
1332 return ret; 1396 return ret;
1333} 1397}
1334EXPORT_SYMBOL_GPL(nvme_init_identify); 1398EXPORT_SYMBOL_GPL(nvme_init_identify);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 14cfc6f7facb..42ede67bfbc6 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -112,6 +112,7 @@ enum nvme_ctrl_state {
112 112
113struct nvme_ctrl { 113struct nvme_ctrl {
114 enum nvme_ctrl_state state; 114 enum nvme_ctrl_state state;
115 bool identified;
115 spinlock_t lock; 116 spinlock_t lock;
116 const struct nvme_ctrl_ops *ops; 117 const struct nvme_ctrl_ops *ops;
117 struct request_queue *admin_q; 118 struct request_queue *admin_q;